# Errors and retries

34 error codes share one structure: each says whether you were charged, whether to retry and what to change. An error costs $0.00, with 1 exception that says so itself: settlement_unknown.

## What an error looks like

The same structure from every endpoint, and from requests that never reached one.

```json
{
  "code": "insufficient_balance",
  "request_id": "8199dc1a-af29-4911-80c8-437718bfa8fb",
  "message": "The balance is too low",
  "message_zh": "余额不足",
  "charged": false,
  "retry": "after_fix",
  "required": "0.002",
  "available": "0.0009",
  "docs_url": "https://dataxapi.com/docs/errors#insufficient_balance"
}
```

## The fields

The first six are always there. The rest appear when they have something to say.

### Always there

| Field | Type | What it tells you |
| --- | --- | --- |
| `code` | string | The stable code. Branch on this, never on the message. |
| `request_id` | string | Names this request. Also in the `X-Request-Id` header. Quote it when you write to us. |
| `message` | string | One sentence in English, taken from the table below. |
| `message_zh` | string | The same sentence in Chinese. |
| `charged` | boolean \| null | `false`: nothing was charged. `null`: not known, which only `settlement_unknown` returns. Never read `null` as free. |
| `retry` | string | `no`, `yes`, `once`, `after_fix` (change the request first) or `same_key` (only with the same Idempotency-Key). |

### When they apply

| Field | Type | What it tells you |
| --- | --- | --- |
| `retry_after_seconds` | integer | How long to wait. The same number as the `Retry-After` header. |
| `param` | string | The parameter that is wrong. |
| `problems` | array | Each thing wrong with the parameters, one by one. |
| `reason` | string | Which case of the code this is: does not exist or is private; rate or concurrency; a key's daily, monthly or total limit. |
| `required` | string | What the call needs, in US dollars. |
| `available` | string | What the balance or the key's limit has left. |
| `docs_url` | url | A link to this code on this page. |

## Every code

34 codes. Only one of them can mean you were charged, and it says so itself.

| HTTP | Code | Meaning | Code, meaning, what to do | Charged | Retry |
| --- | --- | --- | --- | --- | --- |
| 400 | `invalid_params` | A parameter is invalid | Fix the parameter named in `param`. `problems` lists each one. | No | After a fix |
| 400 | `request_not_served` | This combination of parameters cannot be served at present | Drop or change one parameter. The endpoint's page lists the combinations that work. | No | After a fix |
| 400 | `max_price_exceeded` | The most this call could cost is above the limit you set | Raise `X-Max-Price` or leave it out. `required` says what the call can cost. | No | After a fix |
| 400 | `cursor_invalid` | The cursor does not exist | Send `next_cursor` exactly as it came back, or start from the first page. | No | No |
| 400 | `cursor_mismatch` | The cursor was issued for another endpoint or other parameters | Use the cursor with the same endpoint and the same parameters that produced it. | No | After a fix |
| 401 | `unauthorized` | No credential was sent, or it is invalid, disabled or expired | Send `Authorization: Bearer` with your key, and check in the Console that the key is active. | No | No |
| 402 | `insufficient_balance` | The balance is too low | Top up. `required` and `available` give the two amounts. | No | After a fix |
| 402 | `key_budget_exceeded` | This key's spending limit does not cover the call | Raise the key's limit in the Console or use another key. `reason` says daily, monthly or total. | No | After a fix |
| 402 | `run_budget_exceeded` | This run's amount or call limit does not cover the call | Start a new run with a larger budget. A run's budget cannot be raised. | No | No |
| 403 | `account_suspended` | The account is suspended | Write to us. Calls will not work until it is lifted. | No | No |
| 403 | `forbidden` | This credential may not use that option | Remove the header this credential is not allowed to send. | No | No |
| 403 | `key_scope_denied` | This key may not call this endpoint | Add the endpoint to the key's scope in the Console, or use a key that has it. | No | No |
| 404 | `not_found` | The object does not exist, is private or was deleted | Nothing to retry. `reason` says whether it does not exist or is private or deleted. | No | No |
| 404 | `result_not_found` | No result under this request ID | Check the request ID. A call that was released has no result to read. | No | No |
| 404 | `run_not_found` | No run under this run ID | Check the run ID. | No | No |
| 404 | `unknown_endpoint` | There is no such endpoint | Check the path against the API reference. A path is the endpoint ID with the dots turned into slashes. An old path says where it went in `moved_to`. | No | No |
| 409 | `call_in_progress` | The call under this idempotency key is still running; ask again with the same key shortly | Wait a moment, then send the same request with the same `Idempotency-Key`. | No | With the same idempotency key |
| 409 | `idempotency_conflict` | This idempotency key was used for a different request | Use a new key for a new request. | No | After a fix |
| 410 | `cursor_expired` | The cursor expired; start again from the first page | Start again from the first page. `page.cursor_expires_at` tells you in advance. | No | No |
| 410 | `result_expired` | Results are kept for 24 hours; this one is gone | Make the call again. It is a new call and is charged as one. | No | No |
| 410 | `run_expired` | This run has expired and starts no more calls | Start a new run. | No | No |
| 429 | `rate_limited` | Too many requests, or too many calls in progress | Wait `retry_after_seconds` when it is given. Without it, let one of your running calls finish. | No | Yes |
| 429 | `cost_cap_exceeded` | This account's allowance for today is used up | Wait until the time in `Retry-After`. | No | Yes |
| 429 | `uncharged_cost_limit` | Too many of this account's calls today returned nothing and were not charged; endpoints of this kind can be called again tomorrow (UTC) | Wait until tomorrow (UTC); `Retry-After` gives the time. The limit is only on calls that return nothing and are not charged. | No | Yes |
| 500 | `settlement_unknown` | Whether this call settled is not known; ask again with the same idempotency key, or look it up by request ID | Do not assume it was free. Send the same request with the same `Idempotency-Key`, or look the call up by its request ID. | Unknown | With the same idempotency key |
| 500 | `internal_error` | The service failed | Retry. The amount held for the call has been released. | No | Yes |
| 502 | `upstream_failed` | The data source failed | Retry. With the same `Idempotency-Key` it can never be charged twice. | No | Yes |
| 502 | `upstream_changed` | The data source returned an unexpected structure | Retry later. The endpoint may pause itself until it is fixed; Status will say so. | No | Yes |
| 502 | `upstream_unclear` | The data source's answer could not be interpreted; retry at most once | Retry once, then stop. | No | Once |
| 502 | `cursor_unavailable` | The data source this cursor belongs to is unavailable; retry later or start again from the first page | Retry later, or start again from the first page. | No | Yes |
| 503 | `upstream_busy` | The data source is busy; retry shortly | Wait `retry_after_seconds`, then retry. | No | Yes |
| 503 | `capability_paused` | This endpoint is paused | Check Status. Retry once the endpoint is back. | No | Yes |
| 503 | `overloaded` | The service is busy; retry shortly | Wait a few seconds and retry. | No | Yes |
| 504 | `timeout` | The data did not arrive in time; retry with the same idempotency key | Retry with the same `Idempotency-Key`. | No | Yes |

---

Catalog revision c48ce454ae6c4c65. [HTML version](https://dataxapi.com/docs/errors/)
