# Errors

> One error shape, stable codes, what to retry.


Every error has the same shape. `code` is stable and safe to branch on; `message` is for people and may change.

```json
{ "error": { "code": "rate_limited", "message": "Limit is 600 requests a minute for this key." } }
```

| Status | Code | Meaning | Retry? |
|---|---|---|---|
| 400 | `bad_status`, `bad_sort`, `bad_cursor`, `bad_since`, `bad_mints`, `bad_mint`, `bad_json`, `bad_chain`, `basket_type` | A parameter is not one the endpoint takes. The message says what is allowed. | Fix the request |
| 400 | `key_in_url` | A key was put in the URL. | Send it in a header, and revoke it |
| 400 | `bad_wallet`, `bad_name`, `bad_symbol`, `bad_image`, `bad_dev_buy`, `handle_required`, `sol_or_stock`, `split_unsigned`, `not_our_tx` | Launches: a field is missing or wrong, or a signed transaction is missing or was changed. | Fix the request |
| 400 | `basket_size`, `basket_weights`, `basket_asset_not_allowed`, `basket_payback_not_allowed` | Launches: the basket was refused. `error.rejected` gives one reason per asset. | Fix the basket |
| 401 | `missing_key`, `invalid_key` | No key, or the key is wrong or revoked. | No |
| 403 | `signin_required`, `launch_not_allowed`, `opted_out` | A launch key was asked for without a sign-in, the key cannot launch, or the account in `fees_to` opted out. | No |
| 404 | `not_found` | No such coin, account, launch or endpoint. | No |
| 409 | `conflict`, `in_flight` | Launches: already submitted. The error carries the `mint`. | No |
| 410 | `expired` | Launches: signed too late. | Create the launch again |
| 413, 415 | `too_large`, `json_required` | The body is too large, or a key request without a sign-in was not JSON. | Fix the request |
| 429 | `rate_limited`, `daily_quota`, `too_many_bad_keys`, `too_many_new_keys`, `launch_rate_limited` | Over a limit. | After `Retry-After` seconds |
| 503 | `unavailable` | Starting up, or a part that is switched off here. | Yes, with backoff |
| 504 | `unconfirmed` | Launches: sent, not confirmed yet. Never create it again: submit the same launch again or read `GET /launches/{id}`. | Yes, the same launch |
| 504, 410 | `not_landed` | Launches: the network ruled the launch out, so no coin was made. | Create the launch again |
| 500 | `internal` | Our side. | Yes, with backoff |

## A sensible retry

Retry 429, 500, 503 and 504 `unconfirmed` with exponential backoff starting at one second, and always honour `Retry-After`. Never retry a 4xx other than 429 without changing the request.
