code and message are always there. One of details, permission or
retry_after_seconds is added when it applies.
codeis one word from a closed list, for your program to branch on.messageis one sentence, for a person to read. It is the same sentence the console shows for the same refusal, so a marketer and an integrator looking at the same problem see the same words.detailsappears oninvalid_input: a map of field name to a list of messages when the workspace’s own validation refused, or of JSON pointer (/destination) to one message when the request failed schema validation.permissionappears onmissing_permission: the permission the token lacks.retry_after_secondsappears onrate_limited, and on the hourlylimit_reached.
The codes
The list lives in theError schema of the API reference, and that schema is generated
from the API itself, so it is always current. In outline, the codes fall into four
families:
- The door —
unauthenticated(401),subscription_requiredandsubscription_ended(402),missing_permissionandrole_forbids(403),rate_limited(429). See Authentication & tokens and Rate limits. - The plan —
plan_forbids(403) when the plan does not include the feature,limit_reached(429) when one of the two abuse bounds on the Rate limits page is hit, withRetry-Afteronly for the hourly one. A report window the plan does not reach isinvalid_input(422), below. - The rules —
governance_refusedwhen the workspace’s convention, approved values or dependency rules refuse the input,scanner_refusedwhen the destination failed the safety scan,duplicate_linkwhen the workspace already has a link with exactly that tagged destination (409, the only conflict in the set: the message names the existing link, and the right move is to use it rather than retry). The first two are 422. - The request —
invalid_input(422) withdetails, andnot_found(404). A resource of another workspace and one that does not exist are the same answer, on purpose.
How the MCP server reports the same things
A tool call never returns this envelope. A refusal is a tool result flagged as an error, whose text is themessage above, so the assistant can relay it or repair the
input. A protocol-level error means the client spoke wrongly; a refusal means the product
said no. The door’s refusals (401, 402, 429) do apply to the MCP server, and they fail the
connection with that HTTP status rather than a tool result, because a token that is not
admitted has no tools to list.