Skip to content
v0.3

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.