Errors

The uniform error envelope, status rules, and the full error-code table.

Envelope

Every error on every OpenAI-dialect path (/v1/* except /v1/messages) uses one envelope:

{
  "error": {
    "type": "invalid_request_error",
    "message": "…",
    "code": "unsupported_parameter",
    "param": "logit_bias",
    "request_id": "req_01J…"
  }
}
FieldNotes
typeCanonical OpenAI type: invalid_request_error, authentication_error, permission_error, not_found_error, rate_limit_error, insufficient_quota, server_error, api_error.
codeStable machine code — branch on this, never on message.
paramOffending parameter name, or null. Model-scoped rejections always set param: "model".
request_idAlways present; equals the X-TF-Request-Id header.
provider_detailPresent only when the gateway replaced a provider's verbatim message (e.g. provider 5xx).

On /v1/messages the Anthropic envelope is used instead — request_id is a top-level sibling, and there is no code/param:

{"type": "error", "error": {"type": "not_found_error", "message": "…"}, "request_id": "req_01J…"}

Status rules

ScenarioStatustypecode
Body/param validation (before the provider is called)400invalid_request_errorspecific — see table below
Unknown endpoint (path is not a routed inference route, e.g. a typo)404invalid_request_error(none — null)
Unknown / not-allowed model404 / 403not_found_error / permission_errormodel_not_found / model_not_allowed
Provider-native id requested404not_found_errormodel_not_found
Deprecated alias past sunset410not_found_errormodel_deprecated
Image content on non-vision model400invalid_request_errorvision_not_supported
Model does not support the endpoint400invalid_request_errorunsupported_endpoint
Bad API key401authentication_errorinvalid_api_key …
Policy denial (allowlists, plan, project)403permission_errorspecific
Insufficient credit402insufficient_quotainsufficient_funds
Gateway rate limit429 + Retry-Afterrate_limit_errorrate_limit_exceeded
Provider 400400invalid_request_errorprovider_error (verbatim provider message)
Provider 401 / 403502 (provider detail withheld)server_errorprovider_unavailable
Provider 404 / 5xx502server_errorprovider_error
Provider 503503 + Retry-Afterserver_errorprovider_error
Connection failure / no healthy backend503 + Retry-Afterserver_errorprovider_unavailable
Provider timeout504 + Retry-Afterserver_errorprovider_unavailable
Body too large413invalid_request_errorrequest_too_large
Streaming failure after first byte(200 already sent)in-band recordstream_interrupted / api_key_terminated
Async (video) job failure200 on poll; status:"failed" in body—from the job's error object

Two deliberate design choices:

  • 402 is never 429. A funds denial is not congestion — SDK backoff does not help and no Retry-After is sent. Full rationale: Billing.
  • Provider auth failures never reach you as 401/403. A provider rejecting our credential is 502 provider_unavailable — the provider's text is withheld, so you get one clean, actionable error instead of a failure you could not fix anyway.

Model-error taxonomy

SituationStatusCodeparam
Unknown alias, provider-native id404model_not_foundmodel
Model exists but excluded by your key/project allowlist403model_not_allowedmodel
Valid model, wrong endpoint for its mode400unsupported_endpointmodel
Vision mismatch (image content, non-vision model)400vision_not_supportedmodel

Unknown models return the fused wording "does not exist or you do not have access to it" — deliberately, so model existence cannot be enumerated. 403 is returned only where the restriction came from your own configuration.

Error codes

Authentication (401)

CodeMeaning
missing_api_keyNo auth header on the request.
invalid_api_keyKey hash not found.
inactive_api_keyKey deactivated.
expired_api_keyKey past its expiry.

Permission (403)

CodeMeaning
model_not_allowedKey's model allowlist excludes the alias.
model_not_on_planPlan's model allowlist excludes the alias.
project_disabledProject-scoped key whose project is inactive.
organization_suspendedThe key's organization is suspended. Every request is refused until an operator resumes the organization; contact support.
ip_not_allowedClient IP outside the key's (or project's) CIDR allowlist.

Not found / gone (404 / 410)

CodeMeaning
model_not_foundUnknown alias or provider-native id (param: "model").
model_deprecatedAlias past its sunset (message names the replacement).
job_not_foundUnknown or cross-org video job id.

Quota / funds (402 / 429)

CodeStatusMeaning
insufficient_funds402Prepaid wallet cannot cover the reservation. Top up and retry.
key_spend_cap_reached402Per-key USD spend cap reached.
project_quota_exceeded402 / 429Project monthly cost ceiling (402) or project token quota (429).
quota_exceeded429Per-key daily/monthly token quota exceeded.

Rate limits (429)

CodeMeaning
rate_limit_exceededPer-key RPM limit exceeded. Honour Retry-After.
project_rate_limit_exceededProject RPM limit exceeded.
provider_rate_limitedProvider-side 429 — status preserved, provider message verbatim, provider Retry-After forwarded when present.

Request validation (400 / 413)

CodeMeaning
invalid_requestGeneric shape violation (missing messages, negative max_tokens, top_p outside (0, 1] on the completions/responses endpoints, a streaming /v1/completions without stream_options.include_usage: true, non-POST on a JSON endpoint).
invalid_request_bodyBody present but not a JSON object.
invalid_stop_sequencesstop has more than 4 entries.
missing_promptImage/video generation: prompt absent.
empty_promptprompt is empty.
unsupported_response_formatImage response_format:"url" — only b64_json is served.
invalid_image_sizeImage size outside the deployment allowlist.
invalid_tool_call_idrole:"tool" message's tool_call_id doesn't match a preceding assistant tool_calls[].id.
vision_not_supportedImage content sent to a non-vision model (param: "model").
invalid_image_urlimage_url.url empty or not http/https/data scheme.
unsupported_parameterA syntactically valid sampling parameter the backend rejects.
unsupported_endpointModel's catalogue mode doesn't match the endpoint called (param: "model").
request_too_largeBody over the 8 MiB gateway cap (or the image-specific cap).

Server / provider (502 / 503 / 504)

CodeMeaning
provider_errorProvider returned an error (400/404/5xx classes per the status table).
provider_unavailableConnection failure, no healthy backend, provider timeout, or a provider auth failure (401/403 with provider detail withheld).
server_errorGeneric unclassified server error.

In-band stream termination (after a 200)

CodeMeaning
stream_interruptedThe provider's stream was reset.
api_key_terminatedKey revoked mid-stream.

Retrying safely

Error classRetry?How
429 (rate_limit_exceeded, quota_exceeded)YesWait Retry-After seconds, then retry with exponential backoff.
429 provider_rate_limitedYesSame — the provider's own Retry-After is forwarded when present.
502 / 503 / 504YesBackoff with jitter; the request was not metered.
400 / 404 / 410 / 413NoFix the request.
401 / 403NoFix credentials / policy config.
402NoTop up the wallet (or raise the cap), then retry.
In-band stream_interruptedYesRe-issue the request; safe — a partial stream is not billed as complete.

Portal and Management API errors

This page covers the inference API (https://api.<domain>/v1). The Management API (https://portal.<domain>/api/v1/mgmt) uses the same envelope family — an error object with type, code, message, param and request_id — plus an optional action that says how to fix the problem. Its codes, its status rules and the type values it uses are listed in Management API errors.

The same rules apply on both surfaces:

  • Branch on the HTTP status and code. Never parse message; its wording can change.
  • Every response carries a request id, generated by Token Factory; a request id you send is ignored. Quote it when you contact support. Where to find it:
    • Inference API: the X-TF-Request-Id header, repeated as error.request_id (on /v1/messages, as the top-level request_id).
    • Portal and Management API: the X-Request-Id header, repeated as error.request_id.
  • Codes are stable. New codes can appear, so treat an unknown code as the generic error for its status.