Errors are typed by who can fix them. A 4xx is the request or the policy; a 5xx is the pool or the provider.
Status codes
| Code | Meaning | Retry? |
|---|---|---|
| 400 | A parameter or input the pinned model cannot honor, named in the message: a response_format it does not take, or an image, audio, video or tool call its deployment refuses. On /v1/messages, also a malformed request, as Anthropic answers it. On /responses, previous_response_id. A hosted tool type (web_search, file_search, code_interpreter and the like) on /chat/completions or /responses. On an image or audio endpoint, a model that is served on the other endpoint of that kind, which the message names. On /audio/speech, a voice the model does not offer on Inferbase's own routes; the message lists the voices it does. A model of policy: with no slug, an X-Inferbase-Intent header that names no intent, and on /v1/messages or /responses a speech or video intent, which those shapes cannot return. | No |
| 401 | Missing, invalid, revoked or expired API key. The message says which. | No |
| 402 | Insufficient credit, or the conversation has spent the allowance its routing policy sets in session.max_spend_usd. Top up, or start a new session, or raise the cap. | After fixing |
| 403 | The account is deactivated or unverified, or the request asked for something the key's routing policy does not allow. The message names what was refused and what is permitted. The policy cases: a tool outside the allow-list; a routing.model_pool or routing.scope wider than the policy's; a routing.optimize or routing.preset the organization has enforced; a model outside the policy's pool on /embeddings, /rerank, /images/generations, /images/edits, /audio/speech, /audio/transcriptions or /videos, or auto on one of those with no model of that type in the pool; a pinned model or pool member that does not meet a rule pool's conditions; a model of policy:<slug> naming a policy the key may not call, where the message names the ones it may. | No |
| 404 | Model not found, or a model of the wrong kind for the endpoint. Check GET /models. From a signed-in session, a policy:<slug> that no policy in the project or organization answers to. | No |
| 409 | The conversation was stopped by its owner and cannot continue; start a new session or resume it from Agent runs. Also, a request with this Idempotency-Key is still in progress; retry once it completes, and a video downloaded before it finished, which names the state it is in. | Idempotency only |
| 413 | The body exceeds 1 MiB, base64 images and audio included (25 MB for the uploads to /audio/transcriptions and /images/edits), or no model in the pool has a large enough context window. | No |
| 422 | Validation failed, an unrecognized field was sent, or an Idempotency-Key was reused with a different body. error.param names the field. | No |
| 429 | Rate limited, or the model is busy at its providers (the message says so), or the conversation has used the steps its routing policy allows in session.max_steps. Unlike a rate limit, retrying the same session will not clear the step cap. A pinned model that is busy can also be sent as auto. | Rate limit or busy only |
| 502 | The provider returned an error. The model may be cold. | Yes |
| 503 | No eligible model, or every provider it was sent to is busy (the message says so). With auto this is usually a pool or preset problem rather than an outage: nothing in scope satisfies the request's tools, modality, structured output, or quality floor. A rule pool that admits no model at all is reported first. On /embeddings and /rerank, also a pinned provider that is down with fallback refused. On /images/generations, /images/edits, /audio/speech, /audio/transcriptions and /videos, a model whose Inferbase route carries no rate in the unit its provider bills, or a video job whose credential is no longer connected. | After changing the request or the policy |
| 504 | Every attempt in the fallback chain timed out. When a provider also answered that it was busy, the message says the model is busy. | Yes |
Unrecognized parameters are rejected with a 422, not ignored. A parameter that is accepted is either forwarded or refused with a reason, so a 200 always means the request you sent is the request that ran.
The envelope
Error bodies carry both shapes: the OpenAI envelope for OpenAI SDKs, and detail beside it for clients written against the older shape.
{
"error": {
"message": "routing.scope 'all' is wider than the routing policy in force allows (scope 'inferbase'). A request may narrow the policy's scope, never widen it. To route on your provider keys or cloud accounts, set the policy's model pool source to Your own or Mixed.",
"type": "permission_error",
"param": null,
"code": null,
"request_id": "req-9f2c41d8a6b34e17"
},
"detail": "routing.scope 'all' is wider than the routing policy in force allows (scope 'inferbase'). A request may narrow the policy's scope, never widen it. To route on your provider keys or cloud accounts, set the policy's model pool source to Your own or Mixed."
}type follows OpenAI's taxonomy by status: invalid_request_error, authentication_error, permission_error, rate_limit_error, insufficient_quota, api_error, so SDK retry logic works unchanged. param names the field when a field is at fault. code carries the routing disposition on a failure after routing began, and a stable code on the refusals a client is expected to branch on: free_plan_limit and free_plan_capacity on a 402 (Billing); scope_keys_no_connection on a 403 when the request set routing.scope to keys and the project has no provider key or cloud account that serves a chat model; policy_keys_no_connection when the routing policy in force scoped auto to the keys and none is connected. Otherwise null. request_id repeats the X-Request-ID header, so a copied error body is enough to raise a support question.
Every exit uses the envelope, including validation failures, rate limits, timeouts, and oversized bodies rejected before routing. A failure after a stream has started arrives as an event shaped {"object": "error", "error": {...}} followed by [DONE], with the routing disposition in code.
On /v1/messages, errors use Anthropic's envelope instead: {"type": "error", "error": {...}, "request_id": "..."}.
Last updated October 12, 2026.