|

Error Reference

Complete reference for all error codes, HTTP status codes, and troubleshooting steps.

Error Response Format

Every AI Gateway endpoint (chat, vision, audio, embeddings, …) returns errors as flat JSON. The error field is always present and is a string — for gateway-level failures it is a human-readable phrase (with a machine code in code), while endpoint-level failures use the machine code directly as error (e.g. "bad_request").

{
  "error": "Error message describing what went wrong",
  "message": "Human-readable details",
  "code": "machine_code"
}

Fields by failure class:

FieldPresent when
errorAlways (string)
messageMost failures (added to auth failures too)
codeGateway policy failures
reasonsA security guard (input/output) blocked the request
retry_after_msPer-minute rate limit exceeded
balanceCredit balance exhausted
spendSpend cap reached
usageMonthly request limit reached
top_up_url / upgrade_urlCredit/limit failures

The error envelope is not OpenAI's { "error": { "message", "code", "type" } } shape. Parse error as a string.

HTTP Status Codes

StatusMeaningTypical Cause
200OKRequest succeeded
400Bad RequestInvalid parameters, unsupported format/voice/model, file too large, provider rejected the request
401UnauthorizedMissing or invalid API key
402Payment RequiredSpend cap reached
403ForbiddenDomain not allowed, network policy, frozen billing, credit exhaustion
429Too Many RequestsPer-minute rate limit or monthly request limit exceeded
500Internal ErrorServer-side error
502Bad GatewayProvider failed (timeout, upstream 5xx)
503Service UnavailableRate-limit backend unavailable (fail-closed) or network policy unavailable
504Gateway TimeoutProvider request exceeded the 55s budget

Gateway-level Codes

These come from the shared gateway middleware before the endpoint runs:

CodeStatusMeaning
missing_api_key401No CENCORI_API_KEY or Authorization: Bearer header
invalid_api_key401Key missing, revoked, or invalid
domain_not_allowed403Publishable key used from an unapproved Origin
network_access_denied403Request source blocked by the project ingress policy
billing_frozen403Organization billing is frozen
credit_balance_exhausted403Credit-gated tier (Pro/Team) with no credits. Free and Enterprise tiers are not credit-gated. Top up at top_up_url
monthly_request_limit_reached429Organization monthly request cap hit
rate_limit_exceeded429Per-project per-minute limit hit; body carries retry_after_ms, header carries Retry-After
rate_limit_unavailable503Rate-limit backend down and fail-open is disabled
spend_cap_reached402Monthly spend cap hit

Endpoint-level Codes

The AI endpoints return these via error (and code where meaningful):

CodeStatusMeaning
bad_request400Unsupported model/voice/format, invalid temperature/speed, missing file, file over 25MB, text over 4096 chars
provider_not_configured400No API key for the provider (BYOK not set, no managed key)
provider_error400 / 502Upstream provider failed (4xx → 400, 5xx → 502)
provider_timeout504Long-running provider job (e.g. AssemblyAI polling) expired
internal_error500Unexpected server failure

Security guards (input/output) return their own blocked responses with error, message, and reasons in the 4xx range.

Rate Limit Headers

Rate-limited responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp in milliseconds), and every gateway response carries X-Request-Id for correlation.

429 responses also set a standards-compliant Retry-After header in seconds. The same value is available as retry_after_ms in the body.

Error Handling Example

try {
  const response = await cencori.ai.chat({ model: 'gpt-4o', messages });
} catch (error: any) {
  if (error.status === 429) {
    const retryAfter = error.retryAfterMs ?? 60_000;
    // Wait and retry...
  }
}

Troubleshooting

  • credit_balance_exhausted (403) — top up in Organization → Billing. Free/Enterprise tiers aren't credit-gated.
  • rate_limit_exceeded (429) — 60 requests/min per project for all tiers. Back off for Retry-After seconds or use a second project.
  • monthly_request_limit_reached (429) — free tier resets on the monthly cycle (see reset-usage cron).
  • provider_error (400) — read the message; the truncated upstream body is included.