Errors
The error envelope and every error code.
Every error, on every route, has the same shape. Branch on code, never on message: the code is
stable and the message is for people.
The envelope
{
"error": {
"code": "rate_limited",
"message": "the provider is rate limiting; try again shortly",
"kind": "rate_limit",
"scope": null,
"type": "rate_limit_error",
"param": null,
"request_id": "req_...",
"retry_after_ms": 2000
}
}| Field | Always present | Meaning |
|---|---|---|
code | Yes | What went wrong. One of the codes below |
message | Yes | A human-readable explanation. It may change; do not parse it |
kind | Yes | The class of failure: terminal, unavailable, rate_limit, timeout or unknown |
scope | Yes | What the error is about: request, model, route, or null |
type | Yes | The matching OpenAI error type, so an OpenAI SDK raises its usual exception. Do not branch on it |
param | Yes | Reserved, always null. When a refusal is about one field, the message names it |
request_id | No | The request's id, also sent as the x-op-request-id header |
generation_id | No | Present once a generation existed |
retry_after_ms | No | How long to wait before retrying. When present, a Retry-After header carries the same wait in whole seconds |
attempts | No | One entry per endpoint tried, each with its status and kind |
state, usage, cost | No | On 409 idempotency_conflict only. See Idempotency |
Retry or fix
The kind tells you what to do:
terminal: retrying the same request gets the same error. Fix the request, the key or the account first.rate_limit,unavailable,timeout: retry with backoff. HonourRetry-Afterwhen it is sent.unknown: our failure. Retry once, then contact support with therequest_id.
Before you see a retryable error, the gateway has usually already tried every other endpoint that serves the model. See Fallbacks.
Codes
| Code | Status | Kind | Meaning |
|---|---|---|---|
invalid_request | 400 | terminal | The body or a field is not valid. The message names the field |
policy_conflict | 400 | terminal | The request asks for something the key's policy does not allow, such as a looser retention class or another region |
unsupported_capability | 400 | terminal | The request asks for a feature this API does not offer |
context_length_exceeded | 400 | terminal | The input is longer than the model's context window |
unauthorized | 401 | terminal | The API key is missing, unknown, expired or deleted |
budget_exceeded | 402 | terminal | The request would cross the key's monthly spend cap. See Key restrictions and spend caps |
insufficient_credit | 402 | terminal | The account has no prepaid credit left. See Credits and billing |
forbidden | 403 | terminal | The key may not make this request: a model outside its set, or an address outside its IP ranges |
moderation_refused | 403 | terminal | The request was refused on content grounds |
model_not_found | 404 | terminal | GET /v1/models/{id} has no model with this id, or a preset names a model that does not exist. See /models |
no_endpoint_available | 404 | terminal | No endpoint can serve the request: the model id is unknown, or no endpoint passes the request's filters right now. The message lists what excluded them |
job_not_found | 404 | terminal | No job has this id for your account |
run_not_found | 404 | terminal | No workflow run has this id for your account |
idempotency_conflict | 409 | terminal | A chat request with this Idempotency-Key is in progress or finished |
payload_too_large | 413 | terminal | The request body is too large |
rate_limited | 429 | rate_limit | Too many requests right now. See Rate limits |
internal_error | 500 | unknown | The gateway failed to complete the request |
provider_unavailable | 502 | unavailable | No endpoint could complete the request |
provider_empty_response | 502 | unavailable | The endpoint answered with no output |
provider_payment_required | 502 | unavailable | The endpoint could not take the request. Not about your account |
provider_unauthorized | 502 | terminal | The endpoint refused the gateway. Not about your key. Retry later |
snapshot_expired | 503 | unavailable | The gateway's configuration is out of date. Retry shortly |
upstream_timeout | 504 | timeout | The endpoint did not answer in time |
request_timeout | 504 | timeout | The request did not finish within the time allowed for it |
retention_expired | 504 | terminal | A zdr media job did not finish within 24 hours and was discarded. See Data retention |
client_disconnected | none | none | You closed the connection. Recorded in your usage, never sent to you |
A failed media job carries the same code and message in its error field. See
How media jobs work.
Errors during a stream
An error before the first chunk is an ordinary HTTP error with the envelope above. Once a stream
has started, the status is already 200, so a failure arrives as a last chunk with an error
field, then data: [DONE]. Check every chunk for error. See
Streaming.