HatchedDocs
Reference

Error codes

Every stable error code Hatched raises — HTTP status, SDK class, and how to fix.

Every error response follows the canonical envelope:

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Retry after 60s",
    "requestId": "req_abc_123",
    "details": { "...": "..." }
  }
}

The SDK parses this envelope and throws a typed subclass of HatchedError with code, statusCode, requestId, and details.

Catalogue

CodeHTTPSDK classMeaning
unauthorized401UnauthorizedErrorThe API key is missing, invalid, or revoked.
forbidden403ForbiddenErrorKey is valid but lacks permission for this endpoint.
publishable_key_scope403PublishableKeyScopeErrorPublishable key cannot mutate — use a secret key server-side.
resource_not_found404NotFoundErrorThe referenced id does not exist or was archived.
config_version_mismatch409ConfigVersionMismatchErrorThe buddy is pinned to a different config version than expected.
conflict409ConflictErrorA competing mutation won; retry is safe if you re-read state first.
validation_failed422ValidationErrorFields failed schema/business validation. See err.details.fields.
insufficient_balance400InsufficientBalanceErrorBuddy does not have enough coins/tokens for the spend.
rate_limited429RateLimitErrorOver the per-minute quota. Honour err.retryAfter (seconds).
upstream_image_error502UpstreamImageErrorThe art provider failed during hatch/evolve. No ledger writes happened.

unauthorized

  • HTTP status: 401
  • SDK class: UnauthorizedError (from @hatched/sdk-js)
  • Meaning: The API key is missing, invalid, or revoked.
  • Fix: Double-check HATCHED_API_KEY; rotate in Dashboard → Developers if leaked.
  • More: Troubleshooting →

forbidden

  • HTTP status: 403
  • SDK class: ForbiddenError (from @hatched/sdk-js)
  • Meaning: Key is valid but lacks permission for this endpoint.
  • Fix: Check your plan tier or the key's scope.

publishable_key_scope

  • HTTP status: 403
  • SDK class: PublishableKeyScopeError (from @hatched/sdk-js)
  • Meaning: Publishable key cannot mutate — use a secret key server-side.
  • Fix: Move the call to a server route. See Auth model.
  • More: Troubleshooting →

resource_not_found

  • HTTP status: 404
  • SDK class: NotFoundError (from @hatched/sdk-js)
  • Meaning: The referenced id does not exist or was archived.
  • Fix: Verify the id from a recent list/create response.

config_version_mismatch

  • HTTP status: 409
  • SDK class: ConfigVersionMismatchError (from @hatched/sdk-js)
  • Meaning: The buddy is pinned to a different config version than expected.
  • Fix: Migrate the buddy or pin your write to its current config.

conflict

  • HTTP status: 409
  • SDK class: ConflictError (from @hatched/sdk-js)
  • Meaning: A competing mutation won; retry is safe if you re-read state first.
  • Fix: Re-fetch the resource and retry the mutation.

validation_failed

  • HTTP status: 422
  • SDK class: ValidationError (from @hatched/sdk-js)
  • Meaning: Fields failed schema/business validation. See err.details.fields.
  • Fix: Log err.details; fix the failing field and resend.
  • More: Troubleshooting →

insufficient_balance

  • HTTP status: 400
  • SDK class: InsufficientBalanceError (from @hatched/sdk-js)
  • Meaning: Buddy does not have enough coins/tokens for the spend.
  • Fix: Check err.balance / err.required; surface to the user.

rate_limited

  • HTTP status: 429
  • SDK class: RateLimitError (from @hatched/sdk-js)
  • Meaning: Over the per-minute quota. Honour err.retryAfter (seconds).
  • Fix: Let the SDK retry (default on) or backoff manually.
  • More: Troubleshooting →

upstream_image_error

  • HTTP status: 502
  • SDK class: UpstreamImageError (from @hatched/sdk-js)
  • Meaning: The art provider failed during hatch/evolve. No ledger writes happened.
  • Fix: Re-call the operation; idempotent.
  • More: Troubleshooting →

Programmatic handling

import {
  HatchedError,
  ValidationError,
  RateLimitError,
  InsufficientBalanceError,
} from '@hatched/sdk-js';

try {
  await hatched.buddies.spend(buddyId, { amount: 100, reason: "item" });
} catch (err) {
  if (err instanceof InsufficientBalanceError) {
    return showInsufficientFunds(err.balance, err.required);
  }
  if (err instanceof ValidationError) {
    return showFieldErrors(err.details);
  }
  if (err instanceof RateLimitError) {
    return retryLater(err.retryAfter);
  }
  if (err instanceof HatchedError) {
    console.error(err.code, err.requestId, err.message);
  }
  throw err;
}