# Errors

> Every error code of the X-Buddy MCP and REST API, its HTTP status, whether it is safe to retry, and what to do.

Source: https://x.builera.app/docs/en/errors
Last checked: 2026-10-24

MCP and REST share one list of error codes. Match on `code`, never on the message text.

## REST {#rest}

Errors use `application/problem+json` (RFC 9457):

```json
{
  "type": "https://reach-link-craft.lovable.app/docs/api#error-revision_conflict",
  "title": "Someone changed this setting since you read it. Read it again and retry.",
  "status": 412,
  "code": "revision_conflict",
  "message": "Someone changed this setting since you read it. Read it again and retry.",
  "retryable": false,
  "request_id": "req_…",
  "revision": 4,
  "current": {}
}
```

Every response has an `X-Request-Id` header. Errors with `retry_after_s` also send `Retry-After`.

## MCP {#mcp}

The tool result has `isError: true` and its text is the same JSON body, without the REST wrapper fields `type`, `title` and `status`.

## Fields {#fields}

| Field | When |
|---|---|
| `code`, `message`, `retryable` | Always. |
| `retry_after_s` | Wait this long before retrying. |
| `next_action` | A hint for what to do next. |
| `field` | The input field that is wrong. |
| `detail` | More detail, for example which precondition failed. |
| `candidates` | For `ambiguous_account`: `{ account_id, handle, label }` choices. |
| `revision`, `current` | For `revision_conflict`: the stored revision and the current object. |
| `request_id` | Quote it when reporting a problem. |

## All error codes {#all-error-codes}

| Code | HTTP status | Safe to retry | What to do |
|---|---|---|---|
| [`unauthorized`](/docs/en/errors/unauthorized) | 401 | No | Missing or wrong credentials. REST: send `Authorization: Bearer <API key>`. MCP: reconnect to sign in with OAuth. Don't retry with the same bad key. |
| [`connection_not_linked`](/docs/en/errors/connection_not_linked) | 403 | No | The AI app signed in but isn't linked to a workspace. Reconnect and pick a workspace on the X-Buddy consent page. |
| [`integration_paused`](/docs/en/errors/integration_paused) | 403 | No | This connection is paused in X-Buddy (Settings → MCP / API connections). An Owner or Manager must resume it before you call again. |
| [`workspace_integrations_paused`](/docs/en/errors/workspace_integrations_paused) | 403 | No | The workspace has paused every MCP / API connection. An Owner or Manager can turn them back on in Settings → MCP / API connections. |
| [`integration_revoked`](/docs/en/errors/integration_revoked) | 401 | No | The connection or key was revoked. Create a new key or reconnect; don't retry. |
| [`integration_authorization_lost`](/docs/en/errors/integration_authorization_lost) | 403 | No | The connection's creator no longer has this right (role changed or they left). Use a connection created by someone who has it now. |
| [`key_expired`](/docs/en/errors/key_expired) | 401 | No | The API key has expired. Create a new one in Settings → MCP / API connections. |
| [`workspace_suspended`](/docs/en/errors/workspace_suspended) | 403 | No | The workspace is suspended, so no operation runs. Contact the workspace owner. |
| [`forbidden`](/docs/en/errors/forbidden) | 403 | No | The connection creator's current role can't do this. See “Permission needed” on the operation's page. |
| [`read_only`](/docs/en/errors/read_only) | 403 | No | This connection may only read. To write, create a connection without read-only mode. |
| [`message_content_off`](/docs/en/errors/message_content_off) | 403 | No | This connection may list conversations but not read message text. Allow message reading when you reconnect. |
| [`account_not_allowed`](/docs/en/errors/account_not_allowed) | 403 | No | This X account isn't in the connection's account list. Pick another X account or edit the list in Settings → MCP / API connections. |
| [`not_found`](/docs/en/errors/not_found) | 404 | No | Nothing with this id in the workspace (wrong id, deleted, or another workspace). List again and use a fresh id. |
| [`method_not_allowed`](/docs/en/errors/method_not_allowed) | 405 | No | Right path, wrong HTTP method. Check the method on the operation's page or in the OpenAPI document. |
| [`unknown_operation`](/docs/en/errors/unknown_operation) | 404 | No | No such operation or path. Use `tools_search` (MCP) or the OpenAPI document to find the right name. |
| [`invalid_input`](/docs/en/errors/invalid_input) | 422 | No | The input has a wrong type or a missing field. `field` points to the problem; fix it and send again. |
| [`ambiguous_account`](/docs/en/errors/ambiguous_account) | 409 | No | More than one X account matches. Pick an `account_id` from `candidates` and call again — X-Buddy never guesses. |
| [`idempotency_key_required`](/docs/en/errors/idempotency_key_required) | 428 | No | Writes need an idempotency key of 8–128 characters (A–Z a–z 0–9 . _ : -), for example one UUID per intended action. |
| [`idempotency_conflict`](/docs/en/errors/idempotency_conflict) | 409 | No | This key was already used with different input. Use a new key for each intended action; to retry the old one, send exactly the old input. |
| [`idempotency_processing`](/docs/en/errors/idempotency_processing) | 409 | Yes | The earlier call with this key is still running. Wait `retry_after_s` seconds and call again with the same key. |
| [`revision_required`](/docs/en/errors/revision_required) | 428 | No | This setting is versioned. Read it first, then send `expected_revision` (or `If-Match`). |
| [`revision_conflict`](/docs/en/errors/revision_conflict) | 412 | No | Someone changed the setting. The error carries `revision` and `current`: merge your change into `current`, then send it again with `expected_revision = revision`. |
| [`rate_limited`](/docs/en/errors/rate_limited) | 429 | Yes | The connection made more than 600 calls in a minute. Wait `retry_after_s` seconds. This is the API's limit, not an X account limit. |
| [`unsupported_by_account`](/docs/en/errors/unsupported_by_account) | 422 | No | This X account doesn't have that feature on X (for example it needs Premium). Use another X account. |
| [`agent_too_old`](/docs/en/errors/agent_too_old) | 422 | No | The X account's VPS runs an agent too old for this action. It updates itself when idle; try again later. |
| [`conflict`](/docs/en/errors/conflict) | 409 | No | The request conflicts with the current state (for example it already exists or is running). Read the state again before deciding. |
| [`precondition_failed`](/docs/en/errors/precondition_failed) | 422 | No | A condition of this operation isn't met (`detail` says which). Fix that first instead of resending at once. |
| [`internal`](/docs/en/errors/internal) | 500 | Yes | Unexpected X-Buddy error. You may retry after a few seconds with the same idempotency key; quote `request_id` if it keeps happening. |
