# Errors

> The error shapes on each layer, the codes that matter, and what an agent should do with each.

Source: https://docs.indexzero.site/reference/errors



There are three layers a request can fail on, and each has one shape.

## Inside a tool call [#inside-a-tool-call]

A tool that fails returns an MCP tool result marked `isError`, never a dropped connection or a protocol error. The text carries the code, the message, and where possible an actionable hint, so the agent can tell the user what to do rather than retrying.

| Code                     | Meaning                                                                   | What to do                                                            |
| ------------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `INSUFFICIENT_CREDITS`   | The workspace is out of credits.                                          | Stop paid calls. Free tools keep working. Top up or wait for renewal. |
| `PLAN_UPGRADE_REQUIRED`  | The feature needs a higher plan; the message names it.                    | Do not retry. Tell the user which plan unblocks it.                   |
| `PLAN_LIMIT_REACHED`     | A count limit was hit (projects, trackers). The message states the limit. | Archive or delete something, or upgrade.                              |
| `VALIDATION_ERROR`       | An argument was missing or out of range.                                  | Fix the arguments; the message says which.                            |
| `NOT_CONNECTED`          | The project has no Search Console, Analytics, or PostHog connection.      | Connect it in the dashboard.                                          |
| `RECONNECT_REQUIRED`     | A connection exists but its access has lapsed or been revoked.            | Reconnect in the dashboard.                                           |
| `PROVIDER_BILLING_ISSUE` | The upstream data provider refused the call.                              | Not something the user can fix; contact support if it persists.       |

Not-found conditions use plain messages: `Project <id> not found in this workspace.` (the same whether the id is unknown or belongs to someone else), `Tracker <id> not found.`, `No audits found for this project.`

## In front of the endpoint [#in-front-of-the-endpoint]

Authentication failures at the credential layer use the RFC 6749 shape:

```json
{ "error": "invalid_api_key", "error_description": "The provided API key is invalid, expired, or disabled" }
```

| Status | `error`                            | Meaning                                                                                                              |
| ------ | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| 401    | `invalid_api_key`                  | Unknown, expired, or deleted key.                                                                                    |
| 401    | `invalid_token`                    | Missing or expired OAuth token. The response carries `WWW-Authenticate` pointing at the protected-resource metadata. |
| 403    | `insufficient_scope`               | The OAuth token lacks the `mcp` scope. Re-authorize.                                                                 |
| 429    | `rate_limited` or `usage_exceeded` | Too many requests on an API key. Honour `Retry-After` (seconds).                                                     |

A JSON-RPC request that omits the required protocol headers or the `_meta` envelope fails with JSON-RPC error `-32020`. See [Any other client](/agents/other-clients) for the full header set.

## On HTTP endpoints [#on-http-endpoints]

Product HTTP endpoints return one JSON shape:

```json
{ "error": { "code": "PLAN_LIMIT_REACHED", "message": "Your plan includes 3 projects. Upgrade to add more.", "hint": "..." } }
```

| Status | Meaning                                                                                                                                                                                                                               |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | Validation or an impossible action, such as archiving the last active project (`CANNOT_ARCHIVE_LAST_PROJECT`).                                                                                                                        |
| 402    | Out of credits (`INSUFFICIENT_CREDITS`), or a plan gate (`PLAN_UPGRADE_REQUIRED`, `PLAN_LIMIT_REACHED`). Plan gates add a `denial` object with `feature`, `currentPlan`, `requiredPlan`, and for limits `{ name, allowed, current }`. |
| 502    | The data provider failed.                                                                                                                                                                                                             |
| 503    | Payments are not configured on this deployment.                                                                                                                                                                                       |

## Rules of thumb for agents [#rules-of-thumb-for-agents]

* Never retry a 402 or a plan gate; the outcome will not change until the user acts.
* Treat `-32020` as a client bug, not a server outage.
* On 429, wait for `Retry-After` and continue; the limit is per minute.
* When a paid call fails after the balance check, nothing was charged.
