> To find and run AgentRouter tools, connect to https://mcp.agentrouter.to/. To search this documentation, use https://docs.agentrouter.to/_mcp/server. Append .md to a page URL for Markdown. For the documentation index, see https://docs.agentrouter.to/llms.txt.

# Errors

Errors that happen before a run exists use one envelope:

```json
{
  "error": {
    "code": "PRICING_CHANGED",
    "message": "The price of this tool changed since describe; nothing was executed",
    "hints": [{ "code": "DESCRIBE_TOOL", "message": "Read the current contract and pricing_version with describe, then invoke again.", "params": { "tool_id": "exa.search" } }],
    "details": { "current_pricing_version": "…" }
  }
}
```

When a run was created and then blocked or failed, the response is the [Run](/concepts/runs) itself with `status` and `error`, so you always keep the `run_id`. Hints are generated by AgentRouter; provider text never becomes a hint.

## Refused before anything runs (never charged)

| HTTP | Code                                    | What to do                                                                                                         |
| ---- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| 400  | `INVALID_REQUEST`                       | Fix the request body.                                                                                              |
| 400  | `INPUT_INVALID`                         | Fix `input` to match `input_schema`; `details.issues` lists the problems.                                          |
| 400  | `PRICING_VERSION_REQUIRED`              | Describe the tool and send its `pricing_version`.                                                                  |
| 400  | `PRICE_NOT_CLIENT_SETTABLE`             | Remove price or multiplier fields; AgentRouter sets them.                                                          |
| 401  | `UNAUTHENTICATED`, `INVALID_CREDENTIAL` | Send a valid API key or OAuth token.                                                                               |
| 403  | `INSUFFICIENT_SCOPE`                    | The credential lacks a permission (for example `invoke` or `topup`).                                               |
| 404  | `TOOL_NOT_FOUND`, `RUN_NOT_FOUND`       | Use find; runs are visible only to their own account.                                                              |
| 409  | `PRICING_CHANGED`                       | The price changed after describe, including a free promotion ending. Describe again and decide with the new price. |
| 409  | `TOOL_VERSION_CHANGED`                  | Describe again; the schema may have changed.                                                                       |
| 409  | `TOOL_NOT_ENABLED`, `PRICE_UNAVAILABLE` | The tool cannot run right now; choose another.                                                                     |
| 409  | `IDEMPOTENCY_KEY_CONFLICT`              | The key was used for a different request; use a new key.                                                           |

## Blocked runs (recorded, never charged)

These come back as a Run with `status: BLOCKED`, `error.origin: client` and `billing.reason: blocked_before_execution`.

| HTTP | `error.code`                             | Meaning                                                                                                                                                                                                                                                                                               |
| ---- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 402  | `INSUFFICIENT_BALANCE`                   | Available balance cannot cover the hold; the provider was not called and no funds were reserved or charged. Follow `TOP_UP`, or wait for other holds to release, then make a new attempt. See [holds and insufficient balance](/concepts/billing#what-if-my-available-balance-cannot-cover-the-hold). |
| 409  | `MAX_COST_EXCEEDED`                      | This input can cost more than `max_cost_usd`. The `RAISE_MAX_COST` hint gives the amount; raise it only if the user allows.                                                                                                                                                                           |
| 409  | `BUDGET_EXCEEDED`                        | An account, key or session budget would be exceeded.                                                                                                                                                                                                                                                  |
| 409  | `PROMOTION_EXHAUSTED`, `FREE_CALL_QUOTA` | A free promotion's budget or your daily free calls ran out. It never turns into a paid call by itself; describe again to see the current price.                                                                                                                                                       |

Blocked runs do not automatically resume when balance or limits change. After resolving the cause, invoke again with a new `Idempotency-Key` if you use one; the old key keeps returning the original blocked run.

## Failed runs

| `error.origin` | Charged | What to do                                                                                                                                                  |
| -------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`     | No      | The provider returned an error (bad target, not found, rate limit). If `retryable` is true, a `RETRY_LATER` hint gives a delay; a new invoke is a new call. |
| `platform`     | No      | AgentRouter failed. Retry later.                                                                                                                            |

`TIMED_OUT` and `STOPPED` runs are not charged either.

## Other errors

| HTTP | Code                                                              | Meaning                                                                     |
| ---- | ----------------------------------------------------------------- | --------------------------------------------------------------------------- |
| 404  | `NO_RESULT`                                                       | The run has no stored result (it failed, was blocked, or is still running). |
| 410  | `RESULT_EXPIRED`                                                  | The stored result passed its retention.                                     |
| 409  | `RUN_ALREADY_FINISHED`, `RUN_NOT_STOPPABLE`                       | Stop is not possible.                                                       |
| 409  | `NOT_DISPUTABLE`, `DISPUTE_WINDOW_CLOSED`, `DISPUTE_ALREADY_OPEN` | See [disputes](/concepts/feedback-and-disputes).                            |
| 429  | `RATE_LIMITED`                                                    | Slow down.                                                                  |
| 503  | `TOPUPS_UNAVAILABLE`                                              | Top-ups are off; contact support to add funds.                              |

## CLI exit codes

| Code | Meaning                                         |
| ---- | ----------------------------------------------- |
| 0    | OK                                              |
| 1    | Error                                           |
| 2    | Usage                                           |
| 3    | Authentication                                  |
| 4    | Run failed                                      |
| 5    | Price or version changed (nothing ran)          |
| 6    | Blocked by budget or balance                    |
| 7    | Still running (use `runs get --wait`)           |
| 8    | Output file not written (the run is unaffected) |
| 9    | Not found                                       |