> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mage.space/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and retries

> Every error the Mage API returns: the JSON envelope, each HTTP status and error code with its cause, how a failed request reports on a status read, and which calls are safe to retry.

Every error is a JSON envelope with a stable `code`, a `message` for a person, and sometimes more detail. Branch on the code, never on the message text.

```json theme={null}
{
  "error": {
    "code": "insufficient_gems",
    "message": "This generation costs 338 gems and the account balance is too low.",
    "request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
    "gems_required": 338
  }
}
```

## Codes

| HTTP | Code                     | When                                                                                                                                       | Retry                                    |
| ---- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------- |
| 400  | `invalid_request`        | The body is not a JSON object, sets a server-owned field, contradicts the endpoint's architecture, or the `Idempotency-Key` is malformed.  | After fixing the request                 |
| 400  | `invalid_config`         | A field has the wrong type or a value outside its tokens, an input could not be fetched, or a model rule was broken. The message names it. | After fixing the request                 |
| 401  | `unauthorized`           | The key is missing, malformed, unknown, or revoked.                                                                                        | No                                       |
| 402  | `insufficient_gems`      | The balance is below the price. `gems_required` is the price.                                                                              | After adding Gems                        |
| 403  | `forbidden`              | The account cannot generate.                                                                                                               | No                                       |
| 403  | `content_blocked`        | The request was blocked by Mage's content policy before it ran.                                                                            | No                                       |
| 404  | `architecture_not_found` | No such architecture. The catalog lists the ids.                                                                                           | No                                       |
| 404  | `request_not_found`      | No request with this id belongs to the account, or it was not made through the API.                                                        | No                                       |
| 404  | `not_found`              | No such endpoint. `docs_url` points here.                                                                                                  | No                                       |
| 409  | `request_finished`       | Cancel was called on a request that already completed or failed.                                                                           | No                                       |
| 410  | `architecture_retired`   | The architecture was retired.                                                                                                              | With another model                       |
| 429  | `too_many_requests`      | The account has its cap of generations in flight. See [limits](/api/limits).                                                               | After some finish, with backoff          |
| 451  | `content_blocked`        | The request was blocked by an external content restriction.                                                                                | No                                       |
| 500  | `internal_error`         | Something failed on Mage's side. The failure is reported to Mage automatically.                                                            | Yes, with backoff and an idempotency key |

Codes are an open set: a new one may appear within a version. Treat a code you do not know by its HTTP status.

## Refusals that carry a request id

A submit that Mage records before refusing it (`402`, `403`, `410`, `429`, `451`, and a `400` or `500` raised by the run itself) carries `request_id` in the envelope. Its status read reports how the request ended, and its Gems ledger is visible in the app, even if you sent no idempotency key. The key you sent with it is spent: a retry with the same `Idempotency-Key` replays this failed request instead of submitting again. After fixing the cause, submit a new attempt with a new key.

## Failures on a status read

A request that was accepted and then failed reports `status: failed` with `error.code` set to one of these, and `billing` shows both the charge and the refund.

| Code                | Meaning                                                                        | Gems                                                |
| ------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------- |
| `generation_failed` | The generation did not produce output. Most failures are transient; try again. | Refunded                                            |
| `content_blocked`   | Moderation forbade the output, or the model's lab blocked it.                  | Kept for forbidden output; refunded for a lab block |
| `insufficient_gems` | The balance was too low when the run started.                                  | Never charged                                       |

The text of a model's own error is never forwarded.

## Retry policy

* Retry status reads on network errors and `5xx` responses, with exponential backoff and jitter.
* Retry a submit that got no response (a timeout or a network error) with the same [`Idempotency-Key`](/api/requests#retrying-a-submit-safely), so it cannot charge twice.
* An error envelope that carries `request_id` has consumed its key: the refusal is recorded as that request, and the same key replays it. Fix the cause, then submit again with a new key.
* Do not retry `401`, `403`, `404`, `409`, or `451`, and do not retry a `400` without changing the request.
* Wait on `429` and on `402` until requests finish or Gems are added, then submit again, with a new key when the envelope carried `request_id`.
* Give every retry loop a cap on attempts and a deadline.

If you contact [mage@mage.space](mailto:mage@mage.space) about a request, include its `request_id` and roughly when it happened.
