Skip to main content
Every 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?

Should I retryread the headers, not the statusDoes the refusal carry Retry-After, or Retry-After-Ms?Yes: wait that long, then send the same request again409, every 429, 500, and the retryable 503 codesNo: waiting cannot help, change the request or the credentials400, 401, 402, 403, 404, 413, 503 deployment_errorRead Retry-After-Ms first when your client supports it. It is the only one of the two that can express await shorter than a second. On the hosted admission codes the value is an estimate, capped at 8 seconds,so add jitter when many workers share one key.
Should I retryread the headers, not the statusDoes the refusal carry Retry-After, or Retry-After-Ms?Yes: wait that long, then send the same request again409, every 429, 500, and the retryable 503 codesNo: waiting cannot help, change the request or the credentials400, 401, 402, 403, 404, 413, 503 deployment_errorRead Retry-After-Ms first when your client supports it. It is the only one of the two that can express await shorter than a second. On the hosted admission codes the value is an estimate, capped at 8 seconds,so add jitter when many workers share one key.
The absence of the retry headers is a deliberate signal, not an oversight. A 400, 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

A 503 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

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.
A new key here would start new inference work and a second charge. Contact support with request_id instead.
Send the request again with 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.
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 429.
This answer applies on every /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.
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 declared Content-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-Key when you retry, streaming or not.
  • Respect Retry-After, or Retry-After-Ms if your client reads it, on every response that carries them.
  • On the hosted admission 429 codes 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, 404 or 413. 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 409 while the original is open, then the terminal usage and cost as JSON once it settles, never the delivered tokens. See Idempotent retries.

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.