EZAT RouterDocs

Errors

Every HTTP status and error type the gateway returns in the Anthropic and OpenAI formats, what causes each and whether to retry, errors during a stream, and the request ids to send to support.

When to use this page

A request failed and you want to know why, whether to retry it, or what to send to support. Limits and backoff are on Rate limits.

Error format

Errors use the format of the API you called, with the same HTTP status on both.

/v1/* (Anthropic format):

{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "message": "model: anthropic/no-such-model"
  },
  "request_id": "0b1c6f2e-5d4a-4f7e-9a51-3f0e8d2c7b19"
}

/openai/v1/* (OpenAI format):

{
  "error": {
    "message": "The model `anthropic/no-such-model` does not exist or you do not have access to it.",
    "type": "invalid_request_error",
    "param": "model",
    "code": "model_not_found"
  }
}

The Anthropic and OpenAI SDKs turn these into their own error classes (for example NotFoundError), so you rarely parse them yourself. See the error handling sample in curl, Node.js or Python.

Status codes

StatusAnthropic typeOpenAI type / codeCauseRetry?
400invalid_request_errorinvalid_request_error / nullThe body isn't valid JSON, a required field is missing or wrong (model, max_tokens, messages), the model refused a parameter, or the OpenAI-compatible API doesn't support a field you sentNo. Fix the request.
401authentication_errorinvalid_request_error / invalid_api_keyThe key is missing, wrong, revoked or expiredNo. Check the key.
402billing_errorinsufficient_quota / insufficient_quotaThe organization's balance is zero or below, or the key reached its spend limitNo. Add credit or raise the limit.
403permission_errorpermission_error / nullThe key isn't allowed to use this model, or the organization is suspendedNo
404not_found_errorinvalid_request_error / model_not_foundThe model is unknown, retired, or in preview and the key has no preview accessNo. Use a model from Models.
413request_too_largeinvalid_request_error / request_too_largeThe request body is over 32 MBNo. Send less.
429rate_limit_errorrate_limit_error / rate_limit_exceededThe key went over its requests per minute, or the providers are rate limiting this modelYes, after retry-after
500api_errorserver_error / nullAn unexpected error in the gateway or at the providerYes, a few times with backoff
504timeout_errorserver_error / timeoutA non-streaming request took longer than 590 secondsSend it again with "stream": true
529overloaded_error503, server_error / overloadedNo capacity for this model right now, or every provider the gateway tried failedYes, after retry-after

The OpenAI-compatible API returns 503 where the Anthropic format returns 529, because OpenAI clients don't know 529. Its 404 for a model also sets "param": "model".

None of these errors is charged. See How billing works.

Messages you may see

Statusmessage
400Request body is not valid JSON, or <field>: <problem>, such as max_tokens: … or n: only 1 choice per request is supported
401Missing API key. Send it in the x-api-key or Authorization: Bearer header.
401Invalid API key, This API key has been revoked, This API key has expired
402Your credit balance is too low. Add credits in the EZAT Router dashboard.
402This API key reached its daily spend limit of … (or monthly, total)
403This API key is not allowed to use …
403This organization is suspended. Contact support@ezat.io.
404model: <the name you sent>
429This API key exceeded its requests-per-minute limit (retry-after: 30)
429Rate limited upstream. Please retry shortly. (retry-after: 10)
504The model took longer than 590 seconds. Send long requests with "stream": true.
529Overloaded, or … has no available capacity right now (retry-after: 5)

A 400 that the model itself returns (for example a parameter the model doesn't accept) carries the model's own message.

Paths that don't exist

A path the gateway doesn't serve, such as /v1/messages/batches or /v1/files, returns 404 in a plain format, not in either envelope:

{ "statusCode": 404, "message": "Cannot POST /v1/messages/batches" }

Errors during a stream

Once a streamed response has started, the HTTP status is already 200. If something fails after that, the gateway sends one error event and ends the stream. The request is marked Failed in Usage and isn't charged.

Anthropic format: an error event, with no message_stop after it.

event: error
data: {"type":"error","error":{"type":"api_error","message":"Upstream provider error"}}

OpenAI format: a chunk with an error object, then [DONE].

data: {"error":{"message":"Upstream provider error","type":"server_error","param":null,"code":null}}

data: [DONE]

The error types are the same as in the table above. The Anthropic and OpenAI SDKs raise an APIError (or a subclass) when they read it, and don't retry it: send the request again yourself if you want to.

If your client disconnects mid-stream, there is no error event; see interrupted streams.

Request ids

Two response headers identify a request:

HeaderOnValue
request-idMessages and chat completions that passed the gateway's checks and reached a model, successful or not, streamed or notThe id of the request in your Usage
x-request-idEvery response, including refused requestsAn id for this HTTP call. If you send your own x-request-id (letters, digits, ., _, :, -, up to 128 characters), it is used and sent back.
  • In the Anthropic format, the error body's request_id is the x-request-id.
  • On the OpenAI-compatible API, a completion's id is chatcmpl- followed by its request-id.
  • The Anthropic SDKs expose request-id (message._request_id, and error.request_id in Python or error.requestID in Node). For a refused request there is no request-id, so read x-request-id from the error's response headers.
  • The OpenAI SDKs expose x-request-id (completion._request_id, error.request_id in Python, error.requestID in Node).

Contact support

Email support@ezat.io with:

  1. The request-id, if the response had one, and the x-request-id.
  2. The time of the request (with its time zone), the model, and which API you called (/v1/messages or /openai/v1/chat/completions).
  3. The HTTP status and the error message.

Never send your API key. Request and response bodies aren't stored, so include the parts of the request that matter.

For AI agents

  1. Read the HTTP status first, then error.type (Anthropic format) or error.code (OpenAI format).
  2. Don't retry 400, 401, 402, 403, 404 or 413. Fix the request, tell the user to check the key or add credit at https://router.ezat.io/billing, or pick a model from GET https://api.router.ezat.io/v1/models.
  3. Retry 429, 500, 529 and 503 with exponential backoff, waiting at least the retry-after seconds when the header is there. The official Anthropic and OpenAI SDKs already do this, twice by default.
  4. For a 504 timeout_error, resend with "stream": true instead of retrying as is.
  5. A stream can end with an error event (Anthropic) or an error chunk (OpenAI) after a 200. Treat it like a 500.
  6. When reporting a problem, give the user the request-id and x-request-id headers and the time. Never include the API key.

On this page