# Errors

> **TL;DR** — Branch on `error.code`, not the message. Retry only the codes marked Yes, and network errors, with the same `Idempotency-Key`.

Errors are JSON: `{"error": {"code": "...", "message": "..."}}`. Branch on `code`; the message is for people and may change. Every response has an `X-Request-Id` header: quote it to support.

Retry only the codes marked **Yes** below and network errors, with the same `Idempotency-Key`. Wait for `Retry-After` when the response has it, otherwise back off with jitter. Never retry the others: the same request will fail the same way.

| HTTP | `code` | Retry? | What to do |
|---|---|---|---|
| 400 | `invalid_request` | No | The body or a parameter is wrong; the message says which. |
| 400 | `idempotency_key_required` | No | Send an Idempotency-Key header (max 255 chars) on every submit. |
| 400 | `end_user_id_required` | No | end_user_id is required: the id of the person in your app this run is for. |
| 401 | `invalid_api_key` | No | Missing, unknown or revoked API key. |
| 401 | `api_key_expired` | No | This API key has expired. Create or rotate a key. |
| 402 | `wallet_empty` | No | The product wallet and the org pool cannot cover this run. Add money, then retry. |
| 404 | `style_not_found` | No | No style with that id for your org (or not public). |
| 404 | `run_not_found` | No | No run with that id for this product. |
| 404 | `not_found` | No | No such endpoint. |
| 409 | `idempotency_key_reused` | No | This Idempotency-Key was already used with a different body. Use a new key for a new run. |
| 409 | `run_not_cancelable` | No | Only queued runs can be canceled. |
| 413 | `file_too_large` | No | The file is over the size limit for its type. |
| 415 | `unsupported_content_type` | No | Uploads accept JPEG, PNG, WEBP, MP4, MOV and WEBM. |
| 429 | `end_user_cap_reached` | Yes | This end user reached the daily run cap. Retry after the Retry-After header (resets 00:00 UTC). |
| 429 | `gateway_rate_limited` | Yes | A gateway key's product reached its runs-per-minute limit. Retry after the Retry-After header. |
| 500 | `internal_error` | Yes | Something went wrong on our side. Retry with the same Idempotency-Key; quote X-Request-Id to support. |
| 503 | `style_unavailable` | Yes | This style cannot run on a live key right now (no model behind it). Test keys still return a sample. |
| 503 | `uploads_unavailable` | Yes | Uploads are not available on this deployment right now. |

A run that fails after it was accepted is not an HTTP error: the run ends `failed` or `nsfw` with a [free-run reason](https://docs.wandura.ai/developers/api-v2/concepts#free-runs), and you are not charged.

The [Jobs API](https://docs.wandura.ai/developers/api-v2/jobs#errors) uses its own error codes.
