Errors and retries
The error envelope
Section titled “The error envelope”Every error response carries the same JSON shape:
{ "error": { "code": "validation", "message": "documents must not be empty" } }code is a stable identifier you can branch on; message is for humans and may change.
The hierarchy
Section titled “The hierarchy”Each client maps status codes onto typed errors rather than making you inspect numbers:
| Condition | Error |
|---|---|
| 401, 403 | authentication error |
| 400, 422 | validation error |
| 404 | not-found error |
| 429 | rate-limit error, carrying the retry delay when the server sends one |
| 5xx | server error |
| client-side timeout | timeout error |
| method not on this tier | tier error, raised before the request |
All of them descend from one base error, so you can catch broadly or narrowly.
What gets retried
Section titled “What gets retried”Retries are off by default; set the retry count to enable them. For ordinary requests,
all three clients retry transport failures and HTTP 429, 502, 503 and 504 by default,
with exponential backoff. Python and TypeScript event streams are not retried.
Python and TypeScript let you replace the status set with retry_on and retryOn respectively.
Go uses the fixed status set. A server-provided Retry-After can override the delay;
Go reads it for 429 responses and caps the delay at 30 seconds.
Retries also apply to write requests; the clients do not filter by HTTP method or guarantee idempotency. After a transport failure, the server may already have accepted a submission. Keep retries disabled for writes unless repeating the operation is acceptable.
Waiting for a job is not a retry
Section titled “Waiting for a job is not a retry”Polling a job is a separate loop with its own timeout, and it is not affected by the retry
setting. A job that ends failed or cancelled raises rather than returning quietly — the wait
promised a result, so not getting one is an error.