Errors
The error format, every status code, errors in a stream, retries and debugging.
Format
{
"error": {
"code": 400,
"message": "invalid chat completion request",
"metadata": { "fields": { "messages": "messages must be a non-empty array" } }
}
}codeequals the HTTP status.messageis in English. When a provider rejects a request (4xx), its own message is passed on without parts that name the provider or link to it; for a provider rate limit (429) or failure (5xx) the message is the router's.metadata.provider_namenames the region of the provider that failed:globalorru.metadata.fieldsmaps each invalid field to its problem, for400validation errors.
Status codes
| Status | When | Retry? |
|---|---|---|
400 | Invalid body; unknown model (model … is not available); no route for the model and the request (no route of …); a provider rejected the request | No: fix the request |
401 | Invalid, disabled, expired or revoked API key | No |
402 | Not enough PnP, or a key or space budget is reached | After a top-up |
403 | The space has no payer, lost access to it, or is deleted | No |
404 | GET /generation: no such generation in this space | No |
409 | The payer of the space changed during the request | Yes, at once |
413 | The body is over 4 MiB | No |
422 | A provider could not process the request | No |
429 | A router or provider rate limit | Yes, with backoff |
502 | A provider failed before the answer started | Yes, with backoff |
503 | The router could not confirm the payer's balance, its limits are unavailable, or it is overloaded | Yes, with backoff |
504 | A provider did not answer in time | Yes, or use streaming |
Errors in a stream
After a stream has started, the status is 200 and an error arrives as an event with error and finish_reason: "error". See Streaming.
Retries
- Retry
429,502,503,504and409with exponential backoff and jitter. - Do not retry
400,401,402,403,413,422: the same request fails again. - There is no idempotency key, and a retry is a new request. An error the provider returned before the answer started is not billed; after a timeout in the middle of an answer, the part generated is billed. Check
billableof the attempts inGET /api/v1/generationwhen in doubt. - Better than retrying the same model: give fallback models in
models, see Models and routing.
Debugging
- Every response has an
X-Request-Idheader. Mention it when you contact support. - A generation has an id (
idof the response,X-Generation-Idof a stream).GET /api/v1/generation?id=gen-…shows its state, tokens, cost and every attempt with its status, see GET /generation. - The cabinet logs show the same for every call, and the request and answer when content logging is on.