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

# Errors

> Error codes, where they surface, and how an agent should react.

Errors surface at two layers.

## HTTP layer (before any tool runs)

| Status | Body                                                                       | Meaning                                                                                                                                                                                                     |
| ------ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401`  | `{ "error": "unauthorized", "message": "Missing credentials" }`            | No `Authorization: Bearer` header.                                                                                                                                                                          |
| `401`  | `{ "error": "unauthorized", "message": "Invalid or expired credentials" }` | Credential unknown or expired — a typo, revoked/rotated API key, or an expired OAuth access token. Get the current key from the [dashboard](https://ichabod.dev/account), or reconnect the OAuth connector. |
| `404`  | `{ "error": "not_found" }`                                                 | Wrong path — the MCP endpoint is `/mcp`.                                                                                                                                                                    |

Both `401`s carry a `WWW-Authenticate: Bearer resource_metadata="…"` header pointing at the server's [OAuth Protected Resource Metadata](https://mcp.ichabod.dev/.well-known/oauth-protected-resource). OAuth-capable clients (e.g. the claude.ai web connector) use this to start the sign-in flow automatically; API-key clients can ignore it.

## Tool layer

Failed tool calls return an MCP tool error whose text content is JSON:

```json theme={null}
{ "error": "rate_limited", "message": "Rate limit exceeded (100 per hour). Resets at 2026-06-10T13:00:00.000Z." }
```

| Code                   | Meaning                                                                                                                            | Agent reaction                                                                                                               |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `unauthorized`         | Auth context missing on the call.                                                                                                  | Reconnect; verify the header reaches the server.                                                                             |
| `forbidden`            | Tool requires the other profile type (e.g. Seeker key calling `post_role`).                                                        | Don't retry — use the [tools for your side](/tools/overview). A founder who's also a Seeker needs two profiles and two keys. |
| `rate_limited`         | A [rate-limit](/concepts/rate-limits) bucket is exhausted. The call did not go through.                                            | Wait for the `resets_at` in the message; plan ahead with `get_rate_limits`.                                                  |
| `insufficient_balance` | `post_role` or `unlock_seeker` would overdraw [credits](/concepts/credits). Nothing was charged or created.                        | Top up at the [dashboard](https://ichabod.dev/account), then retry.                                                          |
| `validation_error`     | Input failed validation (bad URL/email, no fields on an update, out-of-range value).                                               | Fix the input per the `message`; don't retry verbatim.                                                                       |
| `not_found`            | Target missing **or not in the required state**: role closed/expired or not yours; `unlock_seeker` without a current mutual match. | Re-check via `get_role` / `list_matches`; the precondition, not the ID, is usually what failed.                              |

<Note>
  Tool-layer errors are returned as results (with `isError: true`), not protocol failures — most MCP clients hand the JSON straight to the model, so instructing your agent on these codes is usually all the error handling you need.
</Note>
