Errors and refusals
Every command answers with the same six codes, and every surface maps them: the API returns the HTTP status
below, the CLI exits non-zero and prints the code, MCP returns a tool error carrying it, and the SDK returns
{ ok: false, error } — it does not throw, so a refusal is a value the type system makes you handle rather
than an exception you can forget to catch. The set is frozen; a caller can branch on it.
A refusal is not a failure. forbidden and conflict are the kernel telling a caller something true
about power and about state; only internal means something went wrong.
| Code | HTTP | What it means |
|---|---|---|
conflict |
409 | The command was understood and the state will not have it: a uniqueness already taken, a transition the entity cannot make from where it is. Retrying the same call unchanged produces the same answer. |
forbidden |
403 | The credential is valid and does not carry the scope this command requires. It is a refusal about POWER, not about identity — a different token, not a retry. |
internal |
500 | The kernel failed. Nothing was committed — a command is one transaction, so a failure leaves no half-applied write behind. |
unauthorized |
401 | No usable credential. The token was absent, malformed, expired, or belongs to a generation that has been revoked. |
unknown_command |
404 | No command by that name. Names are the contract and they are generated onto every surface at once, so this means the name is wrong or the kernel is older than the caller. |
validation_failed |
400 | The input did not match the command’s schema. details carries the offending paths — the same schema published on the command’s own page, so a caller can check before sending. |