# Errors & status codes (/docs/reference/errors)

Every status code and error code returned by the endpoints in this reference is
listed here. Other pages link to this one instead of repeating the table, so this
is the copy to trust if you find a disagreement.

A CoreSpeed call fails at one of two layers. An **HTTP failure** — a `4xx` or
`5xx` status — means the request itself was refused. A **tool failure** is an
HTTP `200` whose JSON-RPC result carries `isError: true`: the request was
authorized and the tool refused or failed. Both carry a machine-readable `code`;
branch on it, and treat the `message` or text as prose for humans.

## The HTTP envelope \[#the-http-envelope]

Every HTTP failure uses one **nested** envelope — `error` is an object:

```json title="Nested — every route"
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authorization",
    "message": "Authorization header or x-api-key is required"
  }
}
```

`code` is the stable value to branch on. `type` is derived from the status:

| Status                                   | `type`                  |
| ---------------------------------------- | ----------------------- |
| `400`, `409`, `411`, `413`, `415`, `422` | `invalid_request_error` |
| `401`                                    | `authentication_error`  |
| `402`                                    | `payment_required`      |
| `403`                                    | `forbidden`             |
| `404`                                    | `not_found`             |
| `405`                                    | `method_not_allowed`    |
| `429`                                    | `rate_limit_error`      |
| `500`                                    | `server_error`          |
| `502`, `503`                             | `api_error`             |

A route adds its own facts **inside** `error`: `field` on a validation failure,
`request_id` on a `500`, and so on. Rate limiting — and any `503` that knows
when to come back — also sets the `Retry-After` header and a **top-level**
`retry_after` sibling. Read the header or the sibling — not
`error.retry_after`, which does not exist:

```json title="429 — nested envelope with a sibling field"
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Retry after 60s."
  },
  "retry_after": 60
}
```

Two surfaces answer with a shape of their own:

* A signed artifact download (`GET /artifacts/…`) answers with RFC 9457
  `application/problem+json`.
* The MCP transport answers envelope-level mistakes with a bare JSON-RPC error
  object, below.

## Transport errors on `/mcp` \[#transport-errors-on-mcp]

Identity, rate limiting, and the body-size limit run **first**: `POST /mcp`
checks them ahead of the transport, so an unauthenticated caller gets the
nested `401`, a throttled one gets `429`, and a body over 5 MiB gets
`413 payload_too_large` — the envelopes above — no matter what the request
body or headers look like.

Only once the caller is identified does the Streamable HTTP transport validate
the envelope itself. Those failures answer with a bare JSON-RPC error object —
`{ "jsonrpc": "2.0", "error": { code, message }, "id": null }` — not the
envelope above:

* **406** `-32000` — `Accept` must list **both** `application/json` and `text/event-stream`. Sending only `application/json` fails here, which is why every sample sets both.
* **415** `-32000` — `Content-Type` must be `application/json`.
* **400** `-32700` — Parse error — malformed JSON, or a body that is not a valid JSON-RPC message.
* **400** `-32600` — A JSON-RPC batch (array body). CoreSpeed rejects arrays ahead of the transport so one rate-limit slot cannot carry an unbounded number of tool calls.
* **400** `-32020` — A request on the `2026-07-28` protocol revision whose `Mcp-Method` or `Mcp-Name` header is missing or disagrees with the body. Nothing ran.
* **200** `-32601` — `subscriptions/listen`. CoreSpeed publishes no events, so it refuses the method.

## HTTP status codes \[#http-status-codes]

These can come from any authenticated route, ahead of the route's own codes
(listed per route in the next section).

* **400** `invalid_request` — The body, query, or path parameters failed validation, or the body is not JSON at all. `error.field` names the first offending field when there is one. Fix the request — do not retry it unchanged.
* **401** `missing_authorization` — No `Authorization` and no `x-api-key` header. On `/mcp` the response also carries a `WWW-Authenticate` header pointing at the protected-resource metadata, which is how OAuth-capable clients start browser sign-in.
* **401** `invalid_jwt` — A bearer JWT failed verification. Which token to renew depends on which one you sent: a user session JWT is refreshed against the session issuer, while an MCP OAuth token on `/mcp` has its own issuer and lifecycle and is renewed by re-running the client's browser sign-in — refreshing the session does nothing for it. Both failures answer with this one code.
* **401** `invalid_api_key` — The API key is unknown, revoked, or expired. Replace it — do not retry.
* **402** `no_active_org` — The caller authenticated but no organization resolved. Answered by the key, agent, organization, billing, and connector routes. Open the [dashboard](https://app.corespeed.io) once to finish setup, then sign in again so the client picks up a token that carries the organization. It is **not** an `/mcp` status: `/mcp` mounts no HTTP wallet gate, so a metered `tools/call` answers `200` with `isError` instead — see the tool codes below.
* **402** `payment_required` — The organization wallet has no credit available. Billable operations stop before execution; discovery and account reads still work. Topping up clears it. Over HTTP the media upload routes answer it; on `/mcp` a metered tool answers it as a tool result (below).
* **402** `key_spend_limit_exceeded` — This API key reached its monthly spend cap. Raise the cap or wait for the reset. Caps are request-boundary guardrails, so a call already in flight can finish above the remaining amount.
* **403** `org_suspended` — Administrative suspension. Every organization-scoped route answers it, `/mcp` included, before anything runs. Adding balance does not clear it — contact support.
* **403** `agent_suspended` — The credential belongs to an agent that is suspended. The key itself is fine — resume the agent (its owner or a holder of `agents:manage`, via `manage__agents_update` or the dashboard) instead of rotating anything.
* **403** `agent_retired` — The agent was retired and its keys are being revoked; once the revocation lands the same key answers `401 invalid_api_key`. Nothing restores a retired agent — mint a new one.
* **403** `api_key_cannot_mint` — An API key asked to mint a key (`POST /api-keys`, `POST /agents/:id/keys`). A key's spend cap does not carry to the keys it would mint, so minting is done from a signed-in session or an MCP sign-in. Every other route answers a key as its principal, with the permissions the key was minted with.
* **403** `member_principal_required` — An agent principal called an act that is a member's own: creating an agent (`POST /agents`), the environment writes, or the `/me` user actions (`/me/sync`, `/me/orgs`, `/me/provision`, `/me/analytics-preferences`). A member's own key is admitted like their session.
* **403** `api_key_cannot_decide` — `POST /approvals/:id/decide` was called with an API key (the dashboard's GraphQL mutations answer `API_KEY_CANNOT_DECIDE` the same way). An approval is a person's click between an agent and its write, and a member key is the credential agents run on; decide from the dashboard, Slack, email, or the Tie menu bar app.
* **403** `insufficient_role` — The route needs a permission the caller does not hold; `permission` names it (for example `members:manage` or `billing:manage`).
* **403** `ceiling_exceeded` — `POST /api-keys` asked for a permission the caller's token cannot hand on; `missing` names the slugs. A key never carries more than the token that minted it.
* **404** `endpoint_not_found` — Unknown path, a connector id that is unknown **or not offered on this environment** (the two are deliberately indistinguishable — see [Get connector](/docs/reference/connectors/get)), or a retired per-connector / per-engine MCP URL. Call the unified `POST /mcp`.
* **405** `Allow: POST` — `GET /mcp`. The endpoint is POST-only — there is no SSE downstream. This response has **no body and no error code**: only the `Allow` header.
* **409** `multiple_accounts` — `DELETE /connectors/:id` matched more than one of your private accounts. Remove one directly via `DELETE /connectors/:id/accounts/:accountId`, or use `manage__accounts_remove` with an alias.
* **429** `rate_limit_exceeded` — Too many requests in the current 60-second window. Two independent dimensions are metered: per API key, and per user for session callers — so one runaway key is throttled without affecting the rest of the organization. Wait out `Retry-After` (advisory, matches the window) before retrying; the body repeats it as a top-level `retry_after`.
* **503** `platform_db_unavailable` — The API-key authority, the organization's billing standing, or (on `/mcp`) the caller's tool surface could not be read. CoreSpeed **fails closed** rather than allowing an unverified key or an unjudged metered call, so this is a transient infrastructure state, not a credential problem — retry with backoff.
* **500** `internal_error` — An unexpected gateway error. The body carries `error.request_id`; retry with backoff and quote the id to support.

## Codes by route \[#codes-by-route]

What each route family adds to the table above. Every route that talks to the
payment provider can also answer `503 payment_provider_unavailable` (retry
shortly) or `503 billing_unavailable` (billing is not offered on this
environment).

| Route                                                          | Status and code                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `POST /api-keys`                                               | `400 invalid_request` (`field: permissions` — not an array of strings) · `400 unknown_permission` (`unknown` names the slugs) · `401 session_client_id_missing` (sign in again from a CoreSpeed client) · `403 ceiling_exceeded` (`missing` names the slugs) · `404 WALLET_NOT_FOUND` · `404 environment_not_found` (`environment` names none of yours)                                                                                                                                                                              |
| `PATCH /api-keys/:id`                                          | `403 agent_self_escalation` (an agent key cannot change key settings) · `404 api_key_not_found`                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `DELETE /api-keys/:id`                                         | `404 api_key_not_found` — a key outside the caller's scope reads as absent                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `POST /api-keys/:id/rotate`                                    | `403 ceiling_exceeded` (the key carries a permission the caller cannot hand on; `missing` names it) · `404 api_key_not_found` · `404 WALLET_NOT_FOUND`                                                                                                                                                                                                                                                                                                                                                                               |
| `GET /agents/:id`                                              | `404 agent_not_found`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `PATCH /agents/:id`                                            | `403 insufficient_role` (the owner or `agents:manage`; a transfer needs `agents:transfer`) · `404 agent_not_found` · `409 agent_already_retired`                                                                                                                                                                                                                                                                                                                                                                                     |
| `POST /agents/:id/keys`                                        | `400 agent_key_permissions` (an agent's key carries no permissions) · `401 session_client_id_missing` · `403 insufficient_role` · `404 agent_not_found` · `404 WALLET_NOT_FOUND` · `404 environment_not_found` (`environment` names none of the agent's) · `409 agent_not_active`                                                                                                                                                                                                                                                    |
| `POST /agents/:id/retire`                                      | `403 insufficient_role` · `404 agent_not_found`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `POST /me/provision`                                           | `403 MEMBERSHIP_REVOKED` · `409 provisioning_conflict` · `502 identity_provider_error`                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `POST /me/orgs`                                                | `403 org_create_requires_payment_method` · `409 provision_required` · `502 identity_provider_error`                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `POST /me/sync`                                                | `502 identity_provider_error`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `/me/org` members and invitations                              | `402 plan_member_limit` and `403 member_limit_reached` (inviting past the plan's seats) · `404 not_found` (member or invitation) · `409 last_admin` (the organization must keep one admin) · `502 identity_provider_error`                                                                                                                                                                                                                                                                                                           |
| `POST /checkout/subscribe`                                     | `404 PLAN_NOT_FOUND` · `404 org_not_found` · `409 ALREADY_PRO` · `409 STRIPE_CUSTOMER_INCONSISTENT`                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `POST /checkout/topup`                                         | `403 topup_requires_subscription` · `404 PLAN_NOT_FOUND` · `404 org_not_found` · `409 STRIPE_CUSTOMER_INCONSISTENT`                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `POST /checkout/portal`                                        | `404 no_billing_account`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `POST /checkout/payment-method-setup`                          | `404 org_not_found` · `409 STRIPE_CUSTOMER_INCONSISTENT`                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `/customers/me/*` billing profile and payment methods          | `400 no_org_customer` · `404 payment_method_not_found` · `409 payment_method_in_use` (a method that funds an active subscription cannot be removed)                                                                                                                                                                                                                                                                                                                                                                                  |
| `POST /connectors/org`                                         | `400` `invalid_slug` · `reserved_slug` · `invalid_url` · `unsupported_auth_mode` · `token_required` · `invalid_headers` · `custom_headers_unavailable` · `preregistered_client_required` — `403 admin_required` · `409 slug_taken` · `409 oauth_registration_pending` · `502 oauth_discovery_failed` · `502 oauth_registration_failed`                                                                                                                                                                                               |
| `POST /connectors/org/:slug/refresh`                           | `403 admin_required` · `404 not_found` · `409` `not_connected` / `needs_reauth` / `unauthorized` (the credential needs reconnecting) · `429 cooldown` (one refresh per 60 s, with `Retry-After`) · `502 snapshot_failed` · `503 kv_unavailable` (the refresh cooldown or the snapshot cache could not be read or written; retry)                                                                                                                                                                                                     |
| `DELETE /connectors/org/:slug`                                 | `403 admin_required` · `403 environment_active` (a key bound to an environment) · `409 oauth_registration_pending` · `409 connector_changed` (the registration changed since you read it) · `404 endpoint_not_found`                                                                                                                                                                                                                                                                                                                 |
| `GET /connectors/org/:slug`                                    | `404 endpoint_not_found` for an unknown slug                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `DELETE /connectors/:id`                                       | `409 multiple_accounts` — you have more than one private account of this connector; remove one by id or alias                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `DELETE /connectors/:id/accounts/:accountId`                   | `404 not_found` — no such account, or not one you may remove (with a key bound to an environment: not one of the environment's)                                                                                                                                                                                                                                                                                                                                                                                                      |
| `POST /mcp/env/:name`                                          | `404 environment_not_found` (no environment of yours by that name — a `ping` too) · `403 environment_mismatch` (the key is bound to another environment)                                                                                                                                                                                                                                                                                                                                                                             |
| `/me/environments`, `/me/environments/connections`             | `403 member_principal_required` (an agent principal on a write) · `400 invalid_request` (`name` is not 1–63 lowercase letters, digits or inner hyphens; a malformed `entries` or `tools`) · `400 connection_not_reachable` (`connection_ids` the owner cannot use) · `400 unknown_tools` · `400 tools_empty` · `403 agent_not_manageable` · `404 environment_not_found` (none you may manage) · `404 agent_not_found` · `409 environment_name_taken` · `409 environment_in_use` (`keys`: active keys still bound; revoke them first) |
| `POST /connectors/:id/accounts/:accountId/grants`              | `400` `invalid_request` (`grantee_id` or `tools`) · `invalid_grantee` · `grantee_not_in_org` · `unknown_tools` · `tools_empty` — `404 not_found` (no such account, or not one you may share) · `409 not_shareable` (this connector's personal accounts stay private)                                                                                                                                                                                                                                                                 |
| `DELETE /connectors/:id/accounts/:accountId/grants/:granteeId` | `404 not_found` · `404 grant_not_found` (the account is not shared with that grantee)                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `PUT /connectors/:id/client`                                   | `400 invalid_request` (`client_id` missing) · `403 forbidden` (an organization admin only) · `409 client_id_shared` (a Microsoft connector's app is already registered for a sibling connector, named in `sibling`) · `404 endpoint_not_found` (this connector takes no organization client)                                                                                                                                                                                                                                         |
| `DELETE /connectors/:id/client`                                | `403 forbidden` (an organization admin only) · `404 endpoint_not_found` (no organization client to remove)                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `PUT <upload_url>`                                             | `400` `content_type_required` · `invalid_content_length` · `content_length_mismatch` · `upload_ticket_mismatch` — `403 no_active_org` · `403 capability_disabled` · `404 upload_ticket_invalid` · `405 method_not_allowed` · `411 content_length_required` · `413 payload_too_large` · `413 upload_quota_exceeded` · `502 storage_error` · `502 file_record_failed` · `503` `quota_unavailable` · `authorization_unavailable` · `upload_capacity_exhausted` · `upload_ticket_unavailable`                                            |

## MCP tool errors \[#mcp-tool-errors]

A tool failure is **not** an HTTP failure. The transport answers `200`; the
JSON-RPC result carries `isError: true`, one text block the agent reads, and
the machine-readable half in `structuredContent.error`:

```json title="HTTP 200 with a failed tool"
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "GitHub rate-limited GET /search/repositories with 429 (search_repositories); retry after 30s"
      }
    ],
    "structuredContent": {
      "error": { "code": "rate_limited", "status": 429, "retry_after_seconds": 30 }
    },
    "isError": true
  }
}
```

Always check `result.isError` in addition to the HTTP status, then branch on
`structuredContent.error.code`. Beside `code`, `error` carries only facts that
are safe to publish — a provider's `status`, its `request_id`, a
`retry_after_seconds`, the aliases to choose from — never a provider's body or
a credential.

One refusal keeps an older shape that clients already parse: the pre-flight
hold's JSON envelope is the **text** itself, with no `structuredContent`, and
the hold also names itself in `_meta["io.corespeed/hold"]` as
`{ code, refusal }`:

```json title="HTTP 200 — a hold"
{
  "content": [
    {
      "type": "text",
      "text": "{\"error\":{\"type\":\"payment_required\",\"message\":\"…\",\"code\":\"payment_required\"}}"
    }
  ],
  "isError": true,
  "_meta": { "io.corespeed/hold": { "code": "payment_required", "refusal": "OrgBelowSpendCutoff" } }
}
```

An approval-gated write answers with a receipt instead — `isError: true`, the
approval id in the text, and `_meta["io.corespeed/approval"]` — and
`manage__approval_wait` returns the real result; see
[Approvals](/docs/approvals).

### Codes on every tool \[#codes-on-every-tool]

* **200** `-32602` — A tool name that is unknown or not on this caller's surface. This one is a JSON-RPC `error` (`Tool <name> not found`), not a `result`, so check for `error` as well as `isError`. A typo in `params.name` never surfaces in the HTTP status.
* **200** `Input validation error` — Arguments that fail the tool's `inputSchema`. The result has `isError: true` and the text `Input validation error: Invalid arguments for tool <name>: …`, with no `structuredContent`. The MCP SDK answers before the tool runs.
* **200** `no_active_org` — No organization could be resolved for this sign-in. A browser MCP sign-in without an organization normally has one resolved — or created — on its first call, so this only remains when that could not complete (the identity provider or the platform database was unreachable). Retry shortly; if it keeps failing, open the [dashboard](https://app.corespeed.io) once to finish setup, then sign in again from the MCP client.
* **200** `payment_required` — The organization is on a billing hold, caught before the metered tool executed — the tool-level mirror of the `402` above.
* **200** `key_spend_limit_exceeded` — The API key hit its monthly cap, caught before the metered tool executed.
* **200** `org_suspended` — Administrative suspension. In practice `/mcp` answers the HTTP `403` above before any tool runs; this tool-level mirror is a fallback.
* **200** `platform_db_unavailable` — CoreSpeed could not read the organization's standing, a stored credential, or another record the call needs. Retry shortly.
* **200** `api_key_cannot_mint` — `manage__keys_create` or `manage__agents_key_create` was called with an API key. A key does not mint keys; mint from the dashboard or a signed-in client. Every other `manage__*` tool answers a key as its principal.
* **200** `member_principal_required` — `manage__agents_create` or an `environments_*` write was called by an agent principal. Creating an agent and shaping environments are a member's own acts; a member's own key is admitted like their session.
* **200** `approval_unavailable` — The approval service could not decide whether this write needs an approval, so the tool did not run. Retry shortly.
* **200** `internal` — The call failed inside CoreSpeed. `error.request_id` identifies it; retry once, and quote the id to support if it fails again.
* **200** `invalid_tool_result` — The tool produced a result that breaks its own declared output — a CoreSpeed defect, reported like `internal`, with `request_id`.

`no_active_org`, `payment_required`, `key_spend_limit_exceeded`,
`org_suspended`, and a `platform_db_unavailable` about billing standing are the
pre-flight hold, answered in the JSON-in-text shape above.
`api_key_cannot_mint`, `member_principal_required`, `approval_unavailable`,
`internal`, and `invalid_tool_result` are in `structuredContent.error`.

### Codes on every connector \[#codes-on-every-connector]

Each connector's tools answer in that connector's name, with these codes:

| Code                        | Meaning                                                                                                                                                                                                                  | Move                                                                         |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
| `not_connected`             | No account of this connector is connected for this caller, or none with that alias.                                                                                                                                      | Connect it in [Dashboard → Connectors](https://app.corespeed.io/connectors). |
| `needs_reauth`              | The provider rejected the stored grant, or it can no longer be renewed. The account is now marked `needs_reauth`.                                                                                                        | Reauthorize the account. Do not rotate the CoreSpeed key.                    |
| `ambiguous_account`         | More than one account is connected; `error.aliases` lists them. Nothing was sent.                                                                                                                                        | Pass `account` with one of the aliases.                                      |
| `account_not_found`         | No connected account has that alias; `error.alias` and `error.available`.                                                                                                                                                | Pass one of `available`.                                                     |
| `tool_not_granted`          | The account is shared with you for some tools only, and this tool is not one of them; `error.alias` and `error.allowed`.                                                                                                 | Ask the account's owner to extend the share.                                 |
| `tool_not_in_environment`   | The session runs in an environment that leaves this account or tool out; `error.environment`, `error.alias` and `error.allowed` (empty when no account of the connector is in it).                                       | Edit the environment from a session outside it, or use another URL or key.   |
| `credential_incomplete`     | The stored connection is missing a value the provider needs (an account id, a domain).                                                                                                                                   | Reconnect the account.                                                       |
| `credential_undecryptable`  | The stored credential could not be read.                                                                                                                                                                                 | Reconnect the account.                                                       |
| `token_refresh_failed`      | The provider's token endpoint refused or failed to renew the access token (`error.status` when it answered).                                                                                                             | Retry; if it persists, reconnect.                                            |
| `not_configured`            | This CoreSpeed environment lacks the app registration the call needs. Not your account.                                                                                                                                  | Report it to support; reconnecting does not help.                            |
| `platform_db_unavailable`   | CoreSpeed could not reach its platform database to load the credential.                                                                                                                                                  | Retry shortly.                                                               |
| `upstream_error`            | The provider refused the request. The text carries its status, the route, and its redacted reason; `error` carries `status` for an HTTP refusal, and `request_id` and `retry_after_seconds` when the provider sent them. | Fix the request, or act on the provider's reason.                            |
| `rate_limited`              | The provider rate-limited the call (`status`, and `retry_after_seconds` or `rate_limit_reset_at` when known).                                                                                                            | Wait, then retry.                                                            |
| `upstream_unreachable`      | The provider could not be reached. On a write the text says the change may still have been applied.                                                                                                                      | Check before retrying a write.                                               |
| `upstream_response_invalid` | The provider answered with something that is not the expected response (`error.status` when it had one).                                                                                                                 | As above.                                                                    |
| `cancelled`                 | The call was cancelled before the provider answered.                                                                                                                                                                     | Check before retrying a write.                                               |

Some connectors add codes of their own:

| Connector                                                                                                                                                     | Code                                                                                                                                      | Meaning                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Atlassian, Auth0, Bitbucket, Google Drive, Meta Ads, Slack, X, YouTube                                                                                        | `scope_not_granted`                                                                                                                       | The connection lacks a scope this tool needs (`error.missing` when the connector can name it); reconnect to grant it.                                                                                                                              |
| Blackbaud, Bluesky, Canvas, Slack, Stack Exchange, Twitch, Facebook, Instagram, Pinterest, Reddit, Reddit Ads, Salesforce, WhatsApp                           | `not_configured`                                                                                                                          | This environment lacks the connector's own app registration, key, or approval (for the Composio-managed seven, `error.reason` says whether the managed backend is unconfigured or switched off). Not your account.                                 |
| Atlassian, AWS, Bitbucket, Capsule CRM, ClickUp, Crowdin, Dub, Gmail, Google Drive, Outlook, Outlook Calendar, Photon, Teams Chat, Twilio, YouTube, Zoho Mail | `invalid_input`                                                                                                                           | Arguments that conflict, or a pagination link not issued by this tool for this account; nothing was sent (`error.field` / `error.reason` where given).                                                                                             |
| Dynamics 365                                                                                                                                                  | `invalid_next_link`                                                                                                                       | A `next_link` not issued for this organization and collection; nothing was requested.                                                                                                                                                              |
| Webex                                                                                                                                                         | `invalid_cursor`                                                                                                                          | A `cursor` that is not a `next_cursor` this tool returned for that collection; it was not followed.                                                                                                                                                |
| Slack                                                                                                                                                         | `invalid_arguments`                                                                                                                       | An argument Slack cannot act on, such as a group DM for canvas access (`error.field`).                                                                                                                                                             |
| Atlassian                                                                                                                                                     | `not_found`                                                                                                                               | The Confluence page does not exist.                                                                                                                                                                                                                |
| Atlassian                                                                                                                                                     | `partially_applied`                                                                                                                       | A Jira transition or sprint change landed part of its work (`error.issue_key` and `error.transition_id`, or `error.sprint_id`; `error.comment_added_via`, `error.comment_id`, `error.failed_step`, `error.failed_code`) — do not redo what landed. |
| X                                                                                                                                                             | `not_found`                                                                                                                               | No user has that handle; nothing was sent.                                                                                                                                                                                                         |
| Bitbucket                                                                                                                                                     | `not_found`                                                                                                                               | The repository has no main branch yet, or no branch or tag with that name.                                                                                                                                                                         |
| Photon                                                                                                                                                        | `not_found`                                                                                                                               | Photon answered `404` or `410` (`error.status`).                                                                                                                                                                                                   |
| YouTube                                                                                                                                                       | `not_found`                                                                                                                               | The video or playlist to update is not on YouTube, or not visible to this channel.                                                                                                                                                                 |
| Gmail                                                                                                                                                         | `not_found`, `label_not_found`                                                                                                            | The message, thread, or draft (`error.resource`, `error.id`), or the label (`error.label`, `error.field`), does not exist.                                                                                                                         |
| Bluesky                                                                                                                                                       | `handle_not_found`                                                                                                                        | The handle does not resolve to an account (`error.handle`); nothing was written.                                                                                                                                                                   |
| Bluesky                                                                                                                                                       | `record_not_owned`                                                                                                                        | A delete aimed at a record that is not the connected account's own (`error.collection`).                                                                                                                                                           |
| YouTube                                                                                                                                                       | `concurrent_edit`                                                                                                                         | The resource changed on YouTube while the update was prepared (HTTP 412); nothing was written — run the tool again.                                                                                                                                |
| Google Ads                                                                                                                                                    | `partial_failure`                                                                                                                         | Some operations committed and others were refused; `error.committed` lists what landed.                                                                                                                                                            |
| Gmail                                                                                                                                                         | `partially_applied`                                                                                                                       | The operation did part of its work before failing; `error` lists what was applied (`forwarded`, `failed_source_ids`, `failed_with`, or for a relabel `applied`, `total`, `created_labels`, `failed_with`) — do not redo those.                     |
| Zoho Mail                                                                                                                                                     | `nothing_archived`, `partially_applied`, `scan_limit_reached`                                                                             | `unarchive_emails`: none of the ids were in the Archive folder; a later batch failed after earlier messages moved; or the thread was too long to walk.                                                                                             |
| Meta Ads                                                                                                                                                      | `scope_not_granted`                                                                                                                       | Graph refused with `(#100) Requires <permission>` for a permission the connector requests but the grant lacks (`error.missing`); reconnect to grant it.                                                                                            |
| Photon                                                                                                                                                        | `scope_not_granted`                                                                                                                       | The connection is a sign-in with Photon, and this tool's operation takes only an API key (key management, authorized apps, plan changes); nothing was sent. Connect Photon with a project API key or an Account Service Key.                       |
| Eventbrite                                                                                                                                                    | `venue_address_incomplete`                                                                                                                | The venue lacks address fields Eventbrite requires (`error.missing`).                                                                                                                                                                              |
| Google Drive                                                                                                                                                  | `drive_not_empty`, `drive_emptiness_unconfirmed`                                                                                          | A shared drive still holds items (`error.trashed` when they are in the trash), or Drive could not confirm that it is empty; nothing was deleted.                                                                                                   |
| Atlassian, Google Drive                                                                                                                                       | `no_content`, `media_too_large`                                                                                                           | A download with no content, or past the size limit for a download or a stored file.                                                                                                                                                                |
| YouTube                                                                                                                                                       | `unsupported_media_type`, `media_too_large`                                                                                               | An upload of a type or size the tool does not take.                                                                                                                                                                                                |
| Atlassian, Google Drive                                                                                                                                       | `invalid_file_input`, `upload_quota_exceeded`, `upload_capacity_exhausted`, `quota_unavailable`, `storage_error`, `handle_storage_failed` | Reading a file input or storing a download as an artifact, with the same meanings as in `media__*` below.                                                                                                                                          |
| Google Ads, LinkedIn, Meta Ads, YouTube                                                                                                                       | `invalid_file_input`                                                                                                                      | A file input could not be opened, with the same meaning (and `retryable`) as in `media__*` below.                                                                                                                                                  |
| Auth0                                                                                                                                                         | `self_target_refused`                                                                                                                     | The call would change the Auth0 application CoreSpeed itself connects through.                                                                                                                                                                     |
| Crowdin                                                                                                                                                       | `scan_limit_reached`                                                                                                                      | A filtered project listing stopped before reaching the requested page; use unfiltered pagination.                                                                                                                                                  |
| ClickHouse Cloud                                                                                                                                              | `service_not_running`                                                                                                                     | The Query API did not run the statement: the service is idle (`error.state` is `idle`; call again with `wake_service: true`) or stopped (`stopped`; start it first). Nothing ran.                                                                  |
| Harvest                                                                                                                                                       | `account_not_found`                                                                                                                       | `account_id` is not one of the Harvest accounts this connection reached (`error.available`).                                                                                                                                                       |
| Timely                                                                                                                                                        | `workspace_not_found`                                                                                                                     | `account_id` is not one of the workspaces this connection reached (`error.available`).                                                                                                                                                             |
| X                                                                                                                                                             | `free_write_limit_reached`                                                                                                                | The Free plan's daily write allowance is used up (`error.limit`); it resets at 00:00 UTC.                                                                                                                                                          |
| Facebook, Instagram, Pinterest, Reddit, Reddit Ads, Salesforce, WhatsApp                                                                                      | `identity_mismatch`                                                                                                                       | The stored connection was made for a different CoreSpeed identity, so it was not used; reconnect.                                                                                                                                                  |
| Slack                                                                                                                                                         | `personal_account_required`                                                                                                               | The tool acts as the connecting member, and the selected alias is the organization bot; pass your personal account's alias.                                                                                                                        |
| Slack                                                                                                                                                         | `reserved_channel`, `channel_id_required`, `approval_settings_unavailable`                                                                | Tools may not write to the approval channel; a channel name was passed where an id is needed to check that; or the approval settings could not be read to check it (retry).                                                                        |
| Datadog                                                                                                                                                       | `mongodb_tag_resolution_unsupported`                                                                                                      | Datadog cannot resolve MongoDB instances by tag.                                                                                                                                                                                                   |
| Stripe                                                                                                                                                        | `docs_response_unverifiable`                                                                                                              | An API-reference-only search could not verify Stripe's response (`error.reason`).                                                                                                                                                                  |

`needs_reauth` also covers each connector's own dead-credential signal —
Greenhouse's and Auth0's refused client credentials, Meta's Graph error 190,
an outdated Zotero key, an inactive Composio connection, a dead Slack user
token, an invalid Bluesky session — and `credential_incomplete` a stored API
key that no longer parses.
Slack answers a refusal with Slack's own error string in `error.slack_error`,
and forwards its hosted MCP server's `isError` results verbatim with a note
appended; Linear, monday.com, and Shopify read their GraphQL rate-limit codes
(`RATELIMITED`, complexity limits, `THROTTLED`) as `rate_limited`.

Vendor-hosted connectors (Datadog, Stripe, Sentry, and the other connectors
served from the vendor's own MCP server) forward the vendor's own `isError`
results verbatim. A failure on CoreSpeed's side of that connection answers
`upstream_error` (with `status` for an HTTP refusal, or `required_scopes` for
an `insufficient_scope` challenge), `timeout` (the upstream outcome is
unconfirmed), `cancelled`, `needs_reauth`, or `upstream_url_refused`. The
account codes in the first table above apply to them too.

### Memory, media, web, social, and drive \[#memory-media-web-social-and-drive]

#### `memory__*` \[#memory\_\_]

`structuredContent.error` is `{ code, message, … }`, `message` repeating the
text.

| Code                                                           | Meaning                                                                                                                                                                                                                                |
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_found`                                                    | The memory, link, or proposal is not visible to this caller.                                                                                                                                                                           |
| `invalid_argument`                                             | Content the store refuses (`reason`, `field`); an input outside its rule (`field`, `rule`, and `minimum` or `maximum`); a change to a teammate's memory without a `reason`; or a field only the author may change (`id`, `field`).     |
| `payload_too_large`                                            | Content past the store's limits (`limit`, `maximum`, `field`).                                                                                                                                                                         |
| `quota_exceeded`                                               | The organization's memory storage quota (`quota_bytes`, `used_bytes`).                                                                                                                                                                 |
| `not_owner`                                                    | A teammate's memory (`id`). Only its author changes or deletes it; where archiving is on, archive it with a reason instead.                                                                                                            |
| `archived`, `not_archived`                                     | The memory is archived, so restore it before changing or linking it; or a restore of a memory that is not archived (`id`).                                                                                                             |
| `version_conflict`                                             | The memory changed since it was read (`expected`, `actual`). Read it again and retry.                                                                                                                                                  |
| `proposal_conflict`, `proposal_capacity_exceeded`, `forbidden` | You already have a different pending proposal of this kind, or the proposal is already resolved (`proposal_id`, `status`); too many pending proposals (`limit`, `maximum`); or a withdraw by someone other than the proposal's author. |
| `link_capacity_exceeded`                                       | A new link would pass a limit (`limit`, `maximum`).                                                                                                                                                                                    |
| `backend_unavailable`                                          | Memory is unavailable for this call: no memory database on this environment (`reason: "misconfigured"`, `retryable: false`), or the store failed.                                                                                      |

#### `media__*` \[#media\_\_]

`structuredContent.error` is `{ code, message, retryable, status? }`:
`retryable` says whether the same call may succeed later, and `status` is
present only when an upstream answered with it.

| Code                                                                                                                       | Meaning                                                                                                                                                                           |
| -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `insufficient_balance`                                                                                                     | The wallet cannot cover the model's estimated hold. Top up or pick a cheaper model.                                                                                               |
| `billing_authorization_failed`                                                                                             | The credit hold could not be recorded (`retryable` says whether to try again).                                                                                                    |
| `billing_settlement_failed`                                                                                                | `media__understand`, `media__transcribe`: the answer was produced but could not be settled, so it is withheld; retryable.                                                         |
| `key_spend_limit_exceeded`, `org_suspended`, `no_active_org`                                                               | As above, caught by media's own pre-flight.                                                                                                                                       |
| `pricing_unavailable`                                                                                                      | The model's rate cannot be established right now (retryable), or media generation is not configured on this environment (`retryable: false`).                                     |
| `unknown_model`, `unsupported_model`                                                                                       | Not a valid model id, or outside the image / video / audio catalog.                                                                                                               |
| `catalog_unavailable`                                                                                                      | Model search, lookup, or schema could not be fetched (`retryable` says whether to try again).                                                                                     |
| `invalid_params`                                                                                                           | `input` fails the model's own schema.                                                                                                                                             |
| `invalid_file_input`                                                                                                       | A file input could not be opened — the text says why (not public, no `Content-Length`, an expired link, an unknown handle).                                                       |
| `generation_failed`                                                                                                        | The generation was refused or failed upstream; the text carries the upstream's reason when it gave one. Nothing was charged.                                                      |
| `empty_output`                                                                                                             | The job finished without an extractable file, or the model returned no answer. Nothing was charged.                                                                               |
| `generation_canceled`, `generation_expired`                                                                                | The job was canceled, or passed its deadline. Nothing was charged.                                                                                                                |
| `job_not_found`, `job_not_running`                                                                                         | No such job in this organization; or a cancel on a job that is no longer running.                                                                                                 |
| `job_ledger_failed`                                                                                                        | The job ledger is unavailable; nothing was charged. Retry.                                                                                                                        |
| `invalid_media_url`, `mime_type_required`, `media_too_large`, `unsupported_media_type`, `invalid_media_window`             | `media__understand` input problems: the `media` URL, its type, its size, or the requested time window.                                                                            |
| `file_not_found`, `upload_processing`, `upload_unprocessable`                                                              | The Drive file is unknown, expired, or not visible to you; still being prepared (retryable, nothing charged); or rejected by the analysis backend.                                |
| `upload_quota_exceeded`, `upload_capacity_exhausted`, `quota_unavailable`                                                  | `drive__create_upload`, and `media__understand` when it copies a URL: the organization's `tmp/` space, the platform's upload capacity, or the quota ledger being unavailable.     |
| `understanding_failed`, `rate_limited`, `content_blocked`, `incomplete_output`, `invalid_usage_metadata`, `internal_error` | `media__understand`: the model failed (`status`), rate-limited, blocked the request, returned a cut-off answer, reported no usable usage, or was unavailable.                     |
| `transcription_failed`                                                                                                     | `media__transcribe`: the recording was refused (too long, undecodable, too short); the text carries the reason. Nothing was charged.                                              |
| `upstream_unavailable`                                                                                                     | `media__transcribe`, `media__list_voices`, and a `media__generate` call whose voice could not be checked: the service could not answer right now; retryable. Nothing was charged. |
| `not_configured`                                                                                                           | Media is not configured on this environment.                                                                                                                                      |
| `cancelled`                                                                                                                | The call was cancelled.                                                                                                                                                           |

#### `web__*` and `social__*` \[#web\_\_-and-social\_\_]

| Code                        | Meaning                                                                                                                                                                                                                            |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_input`             | Arguments refused before any request left CoreSpeed (`field` and `reason` from `web__scrape`, `issues` from the other tools).                                                                                                      |
| `upstream_error`            | The search or data supplier refused the request (`status`, and `request_id` and `retry_after_seconds` when sent; social may add `upstream_code`).                                                                                  |
| `rate_limited`              | The supplier rate-limited the call (`status`, and `retry_after_seconds` when sent).                                                                                                                                                |
| `upstream_unreachable`      | The supplier could not be reached, or timed out.                                                                                                                                                                                   |
| `upstream_response_invalid` | The supplier answered with something unreadable (`status`).                                                                                                                                                                        |
| `cancelled`                 | The call was cancelled.                                                                                                                                                                                                            |
| `no_content`                | `web__scrape`: the page had no readable text.                                                                                                                                                                                      |
| `timeout`                   | A live-collection tool (Facebook, Threads, Google Search and Maps, Airbnb, TripAdvisor, Amazon, Zillow) reached `timeout_seconds` before returning any result. Nothing was charged; raise `timeout_seconds` or narrow the request. |
| `collection_failed`         | A live-collection tool's run failed upstream — often an id, URL, or name that does not exist. Nothing was charged.                                                                                                                 |

#### `drive__*` \[#drive\_\_]

`structuredContent.error` is `{ code, message, retryable? }`. Drive calls are
never charged, so nothing is refunded on a failure.

| Code                                                                      | Meaning                                                                                                                                           |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_path`                                                            | The path breaks the Drive's naming rules; the text says which rule.                                                                               |
| `file_not_found`                                                          | No file at that path, file id or version id that you can see.                                                                                     |
| `path_taken`                                                              | `drive__move`: the destination already names a file.                                                                                              |
| `file_too_large`                                                          | A file under `tmp/` is over the per-file limit; put it on a kept path instead.                                                                    |
| `drive_quota_exceeded`                                                    | The write would pass the plan's kept-bytes ceiling (`drive__usage` shows the numbers).                                                            |
| `upload_quota_exceeded`, `upload_capacity_exhausted`, `quota_unavailable` | The organization's `tmp/` pool or the platform's is full, or the ledger that reserves it is unavailable (retryable); uploads expire on their own. |
| `put_raced`, `precondition_failed`                                        | Another write created or changed the path at the same moment; retry the put.                                                                      |
| `storage_error`                                                           | Storage could not be reached (retryable), or the file's storage is not reachable from this deployment.                                            |
| `drive_unavailable`                                                       | The Drive index is unavailable (retryable), or sharing by link or publicly is not configured on this deployment.                                  |
| `content_length_mismatch`                                                 | `drive__put` from a URL: the origin sent fewer or more bytes than its `Content-Length`.                                                           |

### Manage tools \[#manage-tools]

| Code                                                                                                                                                        | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `api_key_cannot_mint`, `member_principal_required`                                                                                                          | A key on a minting tool; an agent principal on a member's own act (above).                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `no_active_org`, `platform_db_unavailable`                                                                                                                  | As above.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `invalid_arguments`                                                                                                                                         | An argument the tool refuses (`field`).                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `api_key_not_found`, `invalid_spend_limit`, `agent_self_escalation`, `org_wallet_missing`                                                                   | `manage__keys_*`: no such key in scope; a cap that is not above zero; an agent key changing key settings; no wallet for the organization.                                                                                                                                                                                                                                                                                                                                                              |
| `session_client_id_missing`                                                                                                                                 | `manage__keys_create`, `manage__agents_key_create`: the session token has no `client_id` claim; sign in again from a CoreSpeed client.                                                                                                                                                                                                                                                                                                                                                                 |
| `ceiling_exceeded`, `unknown_permission`, `agent_key_permissions`                                                                                           | `manage__keys_create`, `manage__agents_key_create`: a slug the caller's token cannot hand on (`missing`; a token from an MCP sign-in hands on none); a slug that is not a permission (`unknown`); any slug on an agent's key.                                                                                                                                                                                                                                                                          |
| `agent_not_found`, `agent_not_active`, `agent_already_retired`, `agent_not_manageable`, `agent_owner_not_member`, `insufficient_role`                       | `manage__agents_*`: no such agent; not active (suspended or retired), so it cannot get a key; retired; the caller is neither its owner nor a holder of `agents:manage`; the new owner is not a member; giving an agent away needs `agents:transfer`.                                                                                                                                                                                                                                                   |
| `account_not_found`, `alias_taken`, `alias_blank`, `alias_reserved`, `alias_ambiguous`, `account_removal_forbidden`                                         | `manage__accounts_*`: no such alias (inside an environment: none of the environment's accounts); the new alias is taken, empty, or reserved for the connector's organization integration; `accounts_remove` matched more than one account; the caller may not remove a shared account.                                                                                                                                                                                                                 |
| `environment_not_found`, `environment_name_taken`, `environment_in_use`, `connection_not_reachable`, `unknown_tools`, `tools_empty`, `agent_not_manageable` | `manage__environments_*` and the key tools' `environment`: none you may manage by that id or name; the owner already has one by that name; active keys are bound to it (`keys`); an entry names an account the owner cannot use (`connection_ids`); a tool list names tools the connector does not publish, or none; only the agent's owner or a holder of `agents:manage` manages its environments.                                                                                                   |
| `environment_active`, `environment_mismatch`                                                                                                                | The session runs in an environment: environments cannot be edited, an agent's key minted, nor a remote MCP server added, refreshed or removed from inside one; a key minted here is bound to this environment and cannot name another.                                                                                                                                                                                                                                                                 |
| `invalid_grantee`, `grantee_not_in_org`, `unknown_tools`, `tools_empty`, `not_shareable`, `ambiguous_account`, `forbidden`, `grant_not_found`               | `manage__accounts_share` and `manage__accounts_unshare`: the grantee is not a `user_…`, `agent_…`, or `org_…` id, or not in this organization; `tools` names tools the connector does not publish (`unknown`), or none; this connector's personal accounts stay private; the alias names both a private and a shared account; only the owner (or, for a shared account, its creator or a holder of `connections:org`) may change its shares; the account is not shared with that grantee.              |
| `connector_not_found`, `connect_link_unsupported`, `connector_not_shareable`, `agent_owner_missing`                                                         | `manage__connectors_connect`: no connector by that id can be connected here (also from `manage__connectors_wait`); the id names a custom MCP server your organization added (connect it in the dashboard); an agent key asked for Slack or Linear, whose personal accounts are never shared (it uses the organization integration); the agent key's agent has no owner to open the link. Inside an environment `manage__connectors_connect` and `manage__connectors_wait` answer `environment_active`. |
| `identity_provider_unavailable`, `switch_org_unsupported`                                                                                                   | `manage__switch_org`: the identity provider did not answer, so nothing changed; or the session has no browser-OAuth client to re-authorize (an API key's organization is fixed by the key).                                                                                                                                                                                                                                                                                                            |
| `admin_required`                                                                                                                                            | A `manage__remote_*` write without `connections:org` (`permission`).                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `slug_taken`, `invalid_url`, `oauth_discovery_failed`, `cooldown`, `snapshot_failed`, `kv_unavailable`, …                                                   | `manage__remote_*`: the same codes as the `/connectors/org` routes above, as tool codes. An unknown slug is `not_found`, and `cooldown` carries `retry_after_seconds`.                                                                                                                                                                                                                                                                                                                                 |
| `feedback_rate_limited`                                                                                                                                     | `manage__send_feedback`: the organization sent its 50 items for the rolling day (`limit`). Tell your user instead of retrying.                                                                                                                                                                                                                                                                                                                                                                         |
| `approval_not_found`                                                                                                                                        | `manage__approval_wait`: no approval with that id for this caller.                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `approval_coordinator_unreachable`                                                                                                                          | The wait lost contact with the approval; call it again with the same id. A call that already ran is never run twice.                                                                                                                                                                                                                                                                                                                                                                                   |
| `approval_arguments_unreadable`                                                                                                                             | The approved call's frozen arguments could not be read, so it was not run.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `approved_tool_unresolvable`                                                                                                                                | The approved tool is no longer available to this caller, so it was not run.                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `approval_settings_unreadable`, `approval_surface_unavailable`                                                                                              | The approved call was not run because CoreSpeed could not read the settings it must run under, or rebuild the caller's tools. The approval is used up; request the call again once CoreSpeed recovers.                                                                                                                                                                                                                                                                                                 |

A pending, denied, or expired card — or one an earlier wait already ran —
comes back as its receipt, with the state in `_meta["io.corespeed/approval"]`.

### Remote MCP servers \[#remote-mcp-servers]

An org-registered server's own `isError` results are forwarded verbatim. When
the call fails on CoreSpeed's side, an `org__<slug>__*` tool answers:

| Code                                                                                                                                 | Meaning                                                                                                                                                                                             |
| ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `not_connected`, `needs_reauth`, `refresh_failed`, `unauthorized`                                                                    | The caller's authorization for this server is missing, dead, could not be renewed (`status`), or was refused. Reauthorize in the dashboard; for a server registered with a static token, re-add it. |
| `oauth_client_missing`, `oauth_client_unreadable`, `credential_undecryptable`                                                        | The registration's OAuth client is missing or unreadable, so a holder of `connections:org` re-registers the server; or the stored credential is unusable, so reconnect it.                          |
| `invalid_url`, `not_https`, `has_credentials`, `credential_in_query`, `has_fragment`, `ip_literal`, `loopback_or_local`, `self_host` | The server's URL is refused by CoreSpeed's URL guard.                                                                                                                                               |
| `redirect_refused`, `response_too_large`, `too_many_tools`, `protocol_error`                                                         | The server redirected, answered past the size limit, listed too many tools, or spoke something that is not MCP.                                                                                     |
| `timeout`, `cancelled`                                                                                                               | The call timed out or was cancelled; its upstream outcome is unconfirmed.                                                                                                                           |
| `upstream_error`                                                                                                                     | The server refused the request (`status` for an HTTP refusal), answered with a JSON-RPC error, or could not be reached. When unreachable, a write may have landed.                                  |
| `platform_db_unavailable`                                                                                                            | As above.                                                                                                                                                                                           |

### Codes in the activity trail only \[#codes-in-the-activity-trail-only]

Some results reach the agent as a receipt or as an upstream's own result, with
no `structuredContent.error`. The organization's
[activity trail](/docs/activity) still records a code for them:
`approval_pending` and `denied_by_policy` (the approval gate's receipts);
`approval_denied`, `approval_pending`, `approval_expired`,
`approval_already_taken` and `approved_call_failed` (`manage__approval_wait`
answering a closed card, or the approved call's own failure); `upstream_error`
(a vendor's or org server's `isError` result, forwarded verbatim);
`component_root_conflict` (Webflow's result, forwarded with advice); and
`approved_tool_unavailable` (the replay of an approved call whose tool is gone).

## Recovery at a glance \[#recovery-at-a-glance]

| Symptom                           | First move                                                                                                                                                                                                                        |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401` on every call               | Check the header form, then whether the key was revoked.                                                                                                                                                                          |
| `429` in bursts                   | Back off for `Retry-After`. The window follows the credential, one or the other: a session call is limited per user, an API-key call per key. A runaway key is throttled on its own without consuming its owner's session window. |
| `402` on billable operations only | Top up. Discovery still works, so the surface is intact.                                                                                                                                                                          |
| `403 org_suspended`               | Support. No client-side fix exists.                                                                                                                                                                                               |
| `403 api_key_cannot_mint`         | Mint the key from the dashboard or a signed-in client; a key does not mint keys.                                                                                                                                                  |
| `403 member_principal_required`   | That act is a member's (create an agent, shape an environment, the `/me` user actions); use a member's credential.                                                                                                                |
| `404` on a tool call URL          | You are calling a retired per-connector URL. Use `POST /mcp`.                                                                                                                                                                     |
| `500` or tool code `internal`     | Retry once with backoff; quote the `request_id` to support.                                                                                                                                                                       |
| Tool missing from `tools/list`    | Capability disabled, or the account is not connected for this caller.                                                                                                                                                             |
| Tool code `needs_reauth`          | Reauthorize the account in the dashboard.                                                                                                                                                                                         |
| Tool code `ambiguous_account`     | Pass `account` with one of `error.aliases`.                                                                                                                                                                                       |