except. All of them derive from CTRLRunError; the
set is closed by the specification and a new one is a specification amendment first.
Each one
CTRLRunError
Base class for every error raised by CTRLRun.InvalidArgument
An argument cannot be accepted as given. An Action field or argument that cannot be canonicalized (SPEC-v0.1 §2.3), and — the same kind of wiring bug — a StateStore transition no record can make, such as committing an effect nobody reserved.PolicyError
The policy is missing, unreadable, or malformed. Raised at load time (SPEC-v0.1 §3.4).EffectKeyError
An effect template cannot be resolved to a key (SPEC-v0.1 §5.1). The action is refused rather than executed without an effect key: an action whose logical effect cannot be identified cannot be protected against duplication.ActionDenied
The action may not run.reason says why, e.g. unknown_action (SPEC-v0.1 §3.4).
AuthorityDenied
The principal holds no grant that covers this action (SPEC-v0.3 §4.3). A subclass ofActionDenied, because an authority denial is the action being denied and
an agent loop’s existing except ActionDenied should keep working. reason is one of the
closed set in §4.3 — no_authority, authority_constraint, authority_expired,
authority_escalation, authority_revoked, authority_unreadable — never a grant id: a
grant may legally be named no_authority, and evidence that can be spoofed by naming a
grant is not evidence. The id travels in grant_id.
AuthorityEscalation
A delegation that may not exist: it is not contained in its parent (SPEC-v0.3 §5.3). Not anActionDenied: nothing was proposed. This is the creation-time vocabulary —
containment, unknown_parent, parent_not_delegable, parent_not_valid,
not_the_subject, max_depth — and it is disjoint from AuthorityDenied’s evaluation
reasons. The two are never used interchangeably.
ApprovalRequired
The action needs a human.request_id is what ctrlrun approve takes (SPEC §4.3).
Raised instead of blocking, so an agent loop can surface the request and come back with
ctrlrun.with_approval(request_id) in context.
ApprovalTimeout
Nobody answered the approval request in time (SPEC-v0.1 §4.3).ApprovalMismatch
The presented approval does not authorize this action (SPEC-v0.1 §4.2).reason is one of unknown, mismatch, or the status the record was in — consumed,
expired, pending, denied.
DuplicateEffect
This logical effect already happened, or is happening now (SPEC-v0.1 §5.4).state is committed — the effect is done — or in_progress, meaning another attempt
holds a live reservation on the key. Neither permits a second execution.
AmbiguousEffect
The outcome of this effect is unknown; only a human may resolve it (SPEC-v0.1 §5.4). Raised for a record already inAMBIGUOUS, and for one whose lease expired mid-flight:
the worker may have died after the remote committed. A retry is refused either way,
until ctrlrun resolve says which it was.
NotExecuted
Raised by an executor to assert the remote side did nothing (SPEC-v0.1 §5.5). This is the only exception that maps toFAILED and therefore permits a retry.
Every other exception is an AMBIGUOUS outcome.
Suspended
Raised by an executor: the remote asked for something before it will finish. SPEC-v0.2 §6.9 in the kernel’s own terms, and modelled the way v0.1 §5.5 models “nothing happened” — an explicit opt-in signal, never a default and never inferred. There is no outcome to record: the effect record staysEXECUTING, its lease is extended, the
continuation is held, and the caller gets this back to relay.
continuation is whatever the remote said to present again. It is opaque here — CTRLRun
never parses it, and only ever compares it with hmac.compare_digest.
IdentityError
A credential was offered and rejected (SPEC-v0.3 §3.2). Not anActionDenied: an agent loop’s except ActionDenied is written to handle a policy
saying no, and a credential that stopped being valid is not that — the same distinction
v0.1 §5.1 draws for EffectKeyError. A missing principal stays
ActionDenied(reason="no_principal"); this is for one that was produced and found wanting,
which includes an expired Principal reaching Control.execute (§2.3).
SchemaMismatch
A store met a database it does not recognise, in either direction (SPEC-v0.6 §3.3). Its own type rather than anInvalidArgument, and the bar it clears is that an operator’s
process refusing to start needs a distinguishable exception: “your database is from the
future” and “your lease is negative” have entirely different remedies, and one bucket for
both would put a schema problem behind a wiring bug.
MissingDependency
An optional extra is not installed (SPEC-v0.2 §1.1, §11). NeverImportError or ModuleNotFoundError: an operator reads those as a broken
package rather than as an option they did not select. The message names the module that
is missing and the command that installs it.
Next
- Fail closed: the table of what is refused, and where.
- Outcomes and AMBIGUOUS:
NotExecutedand why it is the dangerous one. - Get started · Why.