Skip to main content

Status codes

Match on the status first, then on error.code (also sent as the x-sideren-error-code header) when you need the exact reason. The error type follows the protocol you called: invalid_request_error, authentication_error, billing_error (402), permission_error (403), rate_limit_error (429), and api_error or server_error for 5xx (overloaded_error for a capacity shortage on /v1/messages).

Error body shape

Every error returns a JSON body with an error object carrying a type and a message. On the Anthropic endpoint it is Anthropic-shaped:
Anthropic-shaped (/v1/messages)
On the OpenAI endpoints it is OpenAI-shaped:
OpenAI-shaped (/v1/chat/completions, /v1/responses, ...)

Retries and backoff

The retry recipe every production agent should ship:
  • Retry only what can succeed: 429 and 5xx. A 402 (credits used up) or 403 won’t clear by waiting, and any other 4xx will fail identically on every attempt; fix the request instead.
  • Honor retry-after exactly: on 429 and 503 it is the number of seconds until there is room. Waiting less just burns attempts.
  • Exponential backoff with jitter everywhere else — e.g. 1s, 2s, 4s, 8s with ±20% jitter, capped around five attempts.
  • Fail loud after the cap — surface the final error.message; it is written to be actionable.
Minimal backoff loop
The official OpenAI and Anthropic SDKs already do all of this — including honoring retry-after — with no configuration. Hand-rolled HTTP clients are where retries usually go missing.

Streaming failures

If a stream cannot complete, it ends with a protocol-shaped error event rather than silently returning an empty response — your client always learns the turn failed. Treat a mid-stream error like a 5xx: retry the whole request with backoff. Because the model may already have emitted tool calls your client ran, decide in your client whether to send the turn again. See Streaming.