Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vibefollow.com/llms.txt

Use this file to discover all available pages before exploring further.

Vibefollow uses a single error envelope across the API. Every non-2xx response carries a body of this shape:
{
  "errors": [
    {
      "code": "validation_failed",
      "message": "required",
      "field": "external_user_id"
    }
  ]
}
code is machine-readable. message is human-readable. field names the offending field when the server can pinpoint one.

Status reference

StatusClass of problemRetryableTyped SDK error
400Malformed request (not JSON, etc.)NoVibeFollowError
401API key missing or malformedNoAuthError
403API key valid but not authorisedNoAuthError
404Resource not foundNoVibeFollowError
409Conflict (idempotency key reused with different body)NoValidationError
422Validation failedNoValidationError
429Rate limitedYes (auto)RateLimitError
5xxServer errorYes (auto)ServerError
0Network failure (DNS, refused, timeout)Yes (auto)NetworkError
0Webhook signature mismatchNoWebhookSignatureError
The SDK error classes wrap these — you write catch (err) { if (err instanceof AuthError) ... } instead of inspecting status codes by hand.

Error class reference

API key missing, malformed, or revoked. Not retryable.
import { AuthError } from '@vibefollow/sdk';

try {
  await vf.users.signedUp('usr_42');
} catch (err) {
  if (err instanceof AuthError) {
    // Configuration issue — key is missing or revoked. Alert.
    alerts.fire('vibefollow_auth', err.message);
  } else {
    throw err;
  }
}
Request body failed schema validation, or the Idempotency-Key was reused with a different body. .field names the offending field when available.
import { ValidationError } from '@vibefollow/sdk';

try {
  await vf.events.track('feature_used', 'usr_42', {});
} catch (err) {
  if (err instanceof ValidationError) {
    // Bug in our event-emitting code. Log with the field and fix.
    logger.error({ field: err.field, message: err.message }, 'vibefollow validation');
  } else {
    throw err;
  }
}
Rate limit hit. The SDK auto-retries up to maxRetries; surfaced when retries are exhausted. .retryAfterMs carries the server’s Retry-After.
import { RateLimitError } from '@vibefollow/sdk';

try {
  await vf.users.signedUp('usr_42');
} catch (err) {
  if (err instanceof RateLimitError) {
    // Already retried internally. Back off harder on our end.
    await sleep(err.retryAfterMs);
  } else {
    throw err;
  }
}
Server-side problem on Vibefollow’s end. Retryable by definition; surfaced when retries are exhausted.
import { ServerError } from '@vibefollow/sdk';

try {
  await vf.users.signedUp('usr_42');
} catch (err) {
  if (err instanceof ServerError) {
    // Transient. Already retried; surface and continue.
    logger.warn({ status: err.status }, 'vibefollow server error');
  } else {
    throw err;
  }
}
DNS, refused, abort, timeout. Retryable. The SDK auto-retries; surfaced when the retry budget is exhausted.
import { NetworkError } from '@vibefollow/sdk';

try {
  await vf.users.signedUp('usr_42');
} catch (err) {
  if (err instanceof NetworkError) {
    logger.warn({ cause: err.cause }, 'vibefollow network error');
  } else {
    throw err;
  }
}
HMAC mismatch or timestamp outside the ±5 minute window. Not retryable. Return 401 to Vibefollow.
import { WebhookSignatureError } from '@vibefollow/sdk';

try {
  const event = vf.webhooks.constructEvent(rawBody, sigHeader, secret);
  // ...
} catch (err) {
  if (err instanceof WebhookSignatureError) {
    return res.sendStatus(401);
  }
  throw err;
}
Catch this to handle every SDK error uniformly.
import { VibeFollowError } from '@vibefollow/sdk';

try {
  await vf.users.signedUp('usr_42');
} catch (err) {
  if (err instanceof VibeFollowError) {
    logger.error({ status: err.status, code: err.code, message: err.message }, 'vibefollow error');
  }
  throw err;
}

Common codes

CodeStatusMeaning
auth_required401Authorization header missing or malformed
auth_invalid401API key not recognised (revoked or never existed)
forbidden403API key valid but not authorised for this project / resource
validation_failed422Request body failed Zod schema validation
idempotency_key_reuse422Same Idempotency-Key, different body
rate_limited429Rate limit hit; respect Retry-After
server_error5xxVibefollow had a problem
webhook_signature_invalid(n/a)SDK-thrown; HMAC mismatch or timestamp out of tolerance

When a request silently disappears

Vibefollow returns 202 Accepted for ingest endpoints — that confirms enqueue, not processing. If you track() an event but don’t see it in the dashboard, work through this checklist.
1

Check the events log

Look in Settings → Developers → Recent events. Malformed events land in the quarantine view, not the main stream.
2

Check for near-miss event names

Confirm your event name doesn’t collide with a near-miss canonical name (e.g. user_signedUp vs user_signed_up). The dashboard flags near-misses.
3

Confirm the user ID matches

Confirm the external_user_id matches what identify used. Mismatched IDs create orphaned events that are still ingested but not linked.

See also

SDK errors

Full typed error hierarchy with recovery patterns.

API authentication

Wire-level auth failure modes.

Webhook signatures

The WebhookSignatureError case.