Skip to main content

Errors

Failures arrive through two different channels, and the distinction matters: one is a broken request, the other is something the model should read and react to.

Tool errors​

Everything the caller can act on β€” an invalid argument, not found, insufficient scope or permission, a route error β€” comes back as a successful JSON-RPC response whose result is marked isError, carrying the API's own error envelope as text:

{ "jsonrpc": "2.0", "id": 2, "result": {
"isError": true,
"content": [{ "type": "text",
"text": "{ \"error\": { \"code\": \"NOT_FOUND\", \"message\": \"Execution not found\" } }" }]
} }

The code vocabulary is the v1 API's, unchanged. The ones you will meet most:

codeWhen
VALIDATION_ERRORThe arguments failed validation β€” the tool's own (Invalid tool arguments.) or the route's; the details name the fields.
NOT_FOUNDThe record does not exist, was removed or belongs to another organization.
CONFLICTState conflict β€” for example, an environment name already in use.
IDEMPOTENCY_KEY_REUSED, IDEMPOTENCY_REQUEST_IN_PROGRESSSee Idempotency.
FEATURE_NOT_ENABLEDKobana has not enabled this operation for the organization.
ENTITLEMENT_REQUIREDA run without Kadu in the organization's plan.
MISSING_SECRETS, ENVIRONMENT_REQUIREDA run with required secrets missing a value in the environment, or without a valid environment. kadu_tasks_readiness_get checks beforehand.
COST_LIMIT_REACHEDThe organization reached its monthly cost limit.
RATE_LIMITEDThe route's limit was reached β€” see Rate Limiting.
USER_DECLINEDIn era 2026-07-28, you declined or cancelled the confirmation of a destructive tool. Nothing changed.
confirmation_requiredThe tool is destructive, the client cannot confirm in the chat and the token has no person of the organization who could open an approval link. Nothing ran.
confirmation_replayedThe confirmation sent had already been used β€” each one runs a call once. Call the tool again to be asked again. Nothing ran.
confirmation_unavailableThe server could not record the confirmation (or the approval by link) right now, so it refused the tool. Nothing ran; try again later.

And the three the MCP itself adds, because they are about authorization, not about the record:

codeWho fixes it
insufficient_scopeThe token's scope does not reach the tool: the resource is not in the token, or the level it requires (write or delete) is missing. Authorize again granting the missing access, or use a personal token that reaches the resource at the required level.
insufficient_permissionAn administrator of the organization, granting the permission the error names.
not_a_memberAuthorizing the client again with an account that is a member of the organization β€” no permission fixes this.

These three are separate on purpose: they are different conversations, with different people. A single error would say "you can't" without saying whom to ask. See Authentication.

Not everything that does not run is an error​

  • input_required. In era 2026-07-28, the first tools/call of a destructive tool may return resultType: "input_required" with a confirmation request for the user. The client shows the question and re-sends the same call with the answer.
  • approval_required. In other clients, the same call returns, without isError, status: "approval_required" with the approval link. Show the link; do not call the tool again.

Both are the normal flow β€” see Confirming destructive tools.

Protocol errors​

A malformed message gets a JSON-RPC error object, not a result:

CodeMeaning
-32700Parse error β€” the body is not valid JSON (HTTP 400)
-32600Invalid request β€” not a JSON-RPC object, an array (batching is not supported) or a body above 1 MB
-32601Method not found (HTTP 404 in era 2026-07-28)
-32602Invalid params β€” unknown tool or prompt, missing name, invalid prompt argument, resource without permission; in era 2026-07-28, also resource not found
-32002Resource not found β€” 2025 era only (2026-07-28 uses -32602)
-32603Internal error β€” unexpected failure running the tool
-32020Header mismatch β€” in era 2026-07-28, an MCP header does not match the body (HTTP 400)
-32022Unsupported protocol version (HTTP 400)
{ "jsonrpc": "2.0", "id": 3,
"error": { "code": -32601, "message": "Method not found: tools/describe" } }

Transport errors​

Refusals that happen before the JSON-RPC message is read are plain HTTP responses, with the { "error": { "code", "message" } } envelope: missing or invalid token, unknown organization, Origin outside the list, rate limit, body too large, token verification unavailable. They are listed in Authentication β†’ Failure modes.

Why isError and not a JSON-RPC error​

A 404 on an execution is not a defect of the MCP client β€” it is information about the world, and the model on the other side needs it to correct itself. Burying it in a protocol error would make the client treat it as a transport failure, hide the text and, at best, retry the identical call. Hence the rule: if the caller can act on it, it is a result; if the request is broken, it is an error.

Observability​

Each tools/call writes one structured log line with the tool, the organization, the token id, the token kind (OAuth flow or personal), the status and the duration β€” never the arguments, the token or the body. What the tool does goes through the same API route, with the same effects: a run becomes an execution like any other, with the same events and webhooks. Approvals by link are recorded in Settings β€Ί Approvals, with what was asked, the decision, when and the result.