agentsclimarketplace

Klaviyo common errors

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/klaviyo-pack/skills/klaviyo-common-errors

'Diagnose and fix common Klaviyo API errors and exceptions.From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill klaviyo-common-errors

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

5.9 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Klaviyo Common Errors

Overview

Quick reference for the most common Klaviyo API errors with real error payloads, root causes, and solutions. Because Klaviyo returns JSON:API errors (a status code plus a structured errors[] array), this skill walks you from a raw exception to a targeted fix: extract the status code, match it against the catalog, apply the documented remedy.

The full per-status-code catalog and the SDK-level failure table live in references/ to keep this workflow scannable — drill in once you know which status code you are chasing.

Prerequisites

  • klaviyo-api SDK installed (npm install klaviyo-api — note: not @klaviyo/sdk)
  • A private API key (pk_*) exported as KLAVIYO_PRIVATE_KEY
  • Access to the application logs where the failed request was recorded, so you can Read the stack trace and Grep for the status code and error code

Instructions

Step 1: Identify the Error

Extract the status code and error detail from the caught exception. Read the log line or wrap the call so the structured payload is visible:

try {
  await profilesApi.createProfile(payload);
} catch (error: any) {
  console.error('Status:', error.status);
  console.error('Errors:', JSON.stringify(error.body?.errors, null, 2));
  // error.body.errors[] has: { id, code, title, detail, source }
}

If you only have raw logs, Grep for the status code (grep -E "40[0-9]|429|50[0-9]") and the code field to isolate the failing request.

Step 2: Match and Fix

Map the status code to its root cause and remedy. Each row links into the full catalog, which carries the actual response payload and the fix code block:

StatusMeaningMost common root cause
400Bad RequestMissing field, non-E.164 phone, or snake_case instead of camelCase
401UnauthorizedMissing KLAVIYO_PRIVATE_KEY, or a public key used as a private key
403ForbiddenAPI key lacks the required scope (e.g. profiles:write)
404Not FoundWrong resource ID or a dead /api/v2/ path
409ConflictDuplicate — use createOrUpdateProfile upsert
429Rate LimitedExceeded burst (75/s) or steady (700/min); honor Retry-After
500/503Server ErrorKlaviyo-side — check status page, retry with backoff

The most common one, 400, is almost always a casing mismatch (the SDK expects camelCase):

// Wrong: snake_case              // Right: camelCase (SDK convention)
{ first_name: 'Jane' }            { firstName: 'Jane' }

See the full error catalog for every status code's real payload, complete cause list, and fix. For client-side failures that never reach the network (wrong import, response.data vs response.body.data, bad filter syntax) plus copy-paste diagnostic commands, see diagnostics & SDK errors.

Output

Working through this skill produces a diagnosis and a fix, not a generated artifact:

  • The status code and error code identifying the failure class
  • The root cause matched from the catalog
  • A concrete code or config change (casing fix, scope grant, upsert, backoff)
  • For 5xx: confirmation of whether the fault is Klaviyo-side (status page) or yours

Error Handling

  • Status code is missing from the exception — the failure is client-side, not an API response. Check the SDK-level errors table in diagnostics (module-not-found, wrong constructor).
  • 401 persists after setting the key — you are using a public key. Verify with echo $KLAVIYO_PRIVATE_KEY | head -c 3 (must print pk_).
  • 429 with no RateLimit-Remaining header — expected. On a 429 Klaviyo returns only Retry-After; do not depend on the reset headers, honor Retry-After.
  • Fix does not resolve the error — collect evidence with klaviyo-debug-bundle, check status.klaviyo.com, then open a support ticket with the request IDs from the error responses.

Examples

Example — 403 permission_denied on profile create. The exception shows status: 403, detail: "...required scope: profiles:write". Match to the 403 row: the key lacks a scope. Fix: mint a new key with profiles:write at Settings > API Keys. Full payload and the endpoint→scope table are in the error catalog under the 403 section.

Example — intermittent 429 under load. Requests fail once traffic exceeds 700/min. Honor the Retry-After header and back off instead of tight-retrying:

if (error.status === 429) {
  const retryAfter = parseInt(error.headers?.['retry-after'] || '10'); // seconds
  await new Promise(r => setTimeout(r, retryAfter * 1000));
  // then retry
}

More worked cases (400 casing, 404 stale ID, 409 upsert) are in the error catalog.

Resources

What ships with it: 2 files

5.7 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.