4xx and 5xx from the /v1 API uses one envelope, and it is the OpenAI-style envelope, so error handling you already wrote against the OpenAI SDK keeps working unchanged.
type is the broad family, code is the specific reason, and param names the request field when one caused it. Branch on type and code, never on message text. Some errors add fields directly inside error, such as paused_until, limit, or credit amounts, never nested under a details property.
type is one of exactly six values.
There is no refusal without this envelope, including a failure we did not anticipate, which arrives as
500 internal_error rather than an empty body. The one exception is the platform edge rejecting a body far above the size limit before it reaches the gateway at all: that answers FUNCTION_PAYLOAD_TOO_LARGE in plain text, with no envelope and no request id.
Every error response also carries X-Request-Id, matching request_id. Quote it when you contact support.
Should I retry?
The absence of the retry headers is a deliberate signal, not an oversight. A400, 401, 402, 403, 404 or 413 needs a different request or different credentials, and 503 deployment_error needs a change to the deployment, so none of them carry timing.
Status and code reference
Every
503 is in the table below.
The 503 codes
A503 means a dependency the gateway needs was unreachable and it failed closed rather than serving unmetered or unbilled. All of them carry Retry-After except the last.
Hosted-model catch-path
502, 503, and 504 responses also include error.runinfra. Its reason is upstream_error, upstream_unavailable, or deadline, and retryable is true. A non-streaming deadline includes structured remedies: enable stream: true, because response headers arrive with the first token, or use a smaller max_tokens value.
Envelopes that carry more than the table
402 insufficient_credits, with the balance and the top-up link
402 insufficient_credits, with the balance and the top-up link
Credit fields are in cents. These values are an example.Add at least
required_cents - current_balance_cents, then retry. topup_url is absolute so it resolves from a terminal, an SDK exception, or a log line, none of which have an origin to resolve a relative path against.A free_window_ended_at field appears only when the model you called was on a promotional free window that closed within the last seven days, as a UTC RFC 3339 instant describing the same close the message states in words. When there is no recently closed window the field is absent rather than null, which is the usual case. The same field accompanies a 402 account_frozen under the same rule. A model’s price, and whether it is inside a free window, live on that model’s page, never here.503 hosted_model_paused, with the scheduled return
503 hosted_model_paused, with the scheduled return
Retry-After is in seconds and capped at 60, so a long pause never parks a client for hours. If the scheduled return has already passed, the status and code stay the same and only the message changes.A paused model is not a missing model. It still appears in GET /v1/models with availability: "paused", so treat this as retry and poll, never as a reason to drop the model id from your configuration.400 hosted_parameter_not_supported on response_format
400 hosted_parameter_not_supported on response_format
reasoning_effort: "none" beside response_format, or drop the format. The rule is per model, and the affected models are named in what each model supports. Nothing is charged for the refusal, which is the point: the alternative is a 200 carrying a reply your parser rejects, billed in full.429 hosted_admission_congested, a capacity shed
429 hosted_admission_congested, a capacity shed
Under a momentary burst the gateway can shed a request before completing it, when it cannot obtain a datastore connection in time or a bounded lock wait expires. That is a temporary capacity condition, not an outage, so it answers This answer applies on every
429./v1 route, so the same condition never surfaces as a different status elsewhere. The message varies with where the shed happened; the status, type and code do not. Unlike a hosted admission limit, a shed carries no limit field and no X-Hosted-Limit-Scope header, because there is no quota to size against.401 or 403 on a key that looks correct
401 or 403 on a key that looks correct
runinfra login creates a CLI key. It has the same rp_ prefix and 40 character body as a workspace API key and it cannot call the inference API, so it answers authentication_error with the message “This API key is internal and cannot be used for customer inference.” Create a workspace API key in Settings, API keys.A pipeline-scoped key on the flat /v1 base URL answers 400 auth_error, and the message names the pipeline URL to use instead. See Authentication.Payload too large
The 3.5MB ceiling is enforced on the declaredContent-Length and again while the body streams, so an understated Content-Length does not bypass it. It is a limit on the encoded request and is separate from the model context window: split the prompt across requests or send less context.
Well above the limit, around 4MB and beyond, the platform edge rejects the request before the gateway sees it, with a plain-text FUNCTION_PAYLOAD_TOO_LARGE response carrying no JSON envelope and no request id. Treat it as the same instruction: shrink the body.
Retry rules
- Keep the same
Idempotency-Keywhen you retry, streaming or not. - Respect
Retry-After, orRetry-After-Msif your client reads it, on every response that carries them. - On the hosted admission
429codes the value is an estimate, capped at 8 seconds, and it changes between refusals. Add jitter if many workers share one key. - Change the request or the credentials before retrying
400,401,402,403,404or413. They carry no timing, and that is the signal. - Do not replace the key after
422 idempotency_replay_unavailable. - A streaming retry is not replayed as a stream. The same key returns
409while the original is open, then the terminal usage and cost as JSON once it settles, never the delivered tokens. See Idempotent retries.
Related
Rate limits
What each 429 means, and how to back off.
Idempotent retries
Retry safely, streaming or not.
Troubleshooting
Symptom first, from the response you actually got.