Error codes

GENERATED from packages/lint/src/codes.ts — do not edit. Run pnpm --filter @runbooks/lint generate after changing the registry.

Every message this catalog produces carries a code. §18.7 lets the message itself stay short — name the location, name the fix — because the code resolves here, where the rule is explained. A code with no entry would make that a promise the interface does not keep, so the registry is checked against what the source actually emits.

capabilities

capabilities/undeclared

Step needs a capability the runbook does not declare — §12

capabilities[] is a privilege request a client checks against its allowlist. A step reaching past it is either mislabelled or lying, and both end with rights nobody reviewed.

capabilities/redundant

Capability no step uses — §18.5

Over-declaration is how agents end up holding privileges nothing in the procedure needs.

capabilities/unanalyzable

Command cannot be analysed — §12

A step nobody could analyse is a step nobody has checked. Reported rather than passed, because a gate that treats "I could not tell" as "fine" is decoration.

graph

graph/start-not-unique

Not exactly one start — §6

A procedure with two beginnings has no defined first step, and a reader following it would have to choose one arbitrarily.

graph/unreachable

Step cannot be reached — §6

A step nothing leads to is either a missing edge or a step that should not be there. Both are worth knowing before an agent runs it.

graph/dangling-edge

Edge points at nothing — §6

A route to a step that does not exist is a path a run can take and then be lost on.

graph/decision-thin

Decision with fewer than two branches — §6

A decision with one outcome is a check written in the wrong shape.

graph/decision-not-exhaustive

Decision without a default — §6

An agent reaching an answer none of the branches cover would have to invent what happens next, which is the improvisation the graph exists to prevent.

graph/check-unrouted

Check with no failure route — §6

A check whose expectation does not hold has to go somewhere, or the supervisor decides for itself.

graph/destructive-unpaired

Destructive step with neither gate nor rollback — §6

The rule the whole product exists to enforce: destructive work is always paired with a human decision before it or a way back after it.

graph/unbounded-cycle

Loop that is not a bounded retry — §6

An unbounded loop in an autonomous agent costs money and causes incidents until somebody notices.

graph/implicit-terminal

Step that ends by running out — §6

A graph may not end by having nowhere to go: a run that stopped somewhere undeclared cannot say whether it succeeded.

graph/step-without-tool

An action or check that names no tool — §6

A reader has to guess what performs it and a supervisor has nothing to scope. Not blocking — a wait, a decision and an escalate have nothing to invoke — but a procedure that does not say what it does is worth less.

graph/branch-check-without-expect

A branch leading to a check with no expectation — §6

The branch asked a question and the step it leads to does not say what answer would mean it went right, so the reader who took that branch cannot tell whether they are still on the path they chose.

graph/too-many-nodes

More than twelve steps and nothing decomposes it — §18.6

Past twelve a graph stops being readable at a glance, which is the only reason to draw one.

ids

ids/duplicate

Duplicate step id — §5

Every reference to the id becomes ambiguous, including the one a supervisor follows at run time.

injection

injection/instruction-override

Overrides the reader's instructions — §12

Catalog content is untrusted input for the agent reading it. A step describes a procedure to whoever runs it; it does not address the reader.

injection/role-assignment

Assigns the reader a role — §12

Catalog content is untrusted input for the agent reading it. A step describes a procedure to whoever runs it; it does not address the reader.

injection/system-prompt-mimicry

Imitates a prompt boundary — §12

Catalog content is untrusted input for the agent reading it. A step describes a procedure to whoever runs it; it does not address the reader.

injection/output-coercion

Dictates how the reader should answer — §12

Catalog content is untrusted input for the agent reading it. A step describes a procedure to whoever runs it; it does not address the reader.

injection/tool-coercion

Tells the reader to skip an approval — §12

The one thing a runbook may never say. An approval exists because someone decided the step needed one.

injection/exfiltration

Instructs the reader to send credentials somewhere — §12

Catalog content is untrusted input for the agent reading it. A step describes a procedure to whoever runs it; it does not address the reader.

injection/hidden-content

Content a reviewer does not see — §12

A human reviewer reads the rendered text and a parser reads the source. Anything only one of them sees is worth flagging.

licence

licence/missing

No licence — §10.2

An SPDX identifier decides whether a record may be indexed at all, and whether it may be adapted.

licence/unrecognised

Licence not recognised — §10.2

Whether the licence permits adaptation cannot be decided automatically, so a human classifies it once rather than the pipeline guessing permissive.

licence/not-indexable

Licence forbids indexing — §10.2

The terms are ones this catalog cannot satisfy by indexing the record at all. A non-commercial clause is here rather than under link-only because whether a catalog is commercial use is not a question we can answer on a publisher's behalf.

provenance

provenance/unobserved-state

The upstream is marked moved with no date for the observation — §3

changed and gone are claims that the source is not what it was, and without checked_at there is no moment at which anybody established that. A marker with no date is a claim about the present made at an unknown time; pnpm reindex writes the two together.

provenance/incomplete

Missing provenance — §10

Every record carries where it came from. Without it a record cannot be traced back, re-verified, or taken down.

publisher

publisher/confusable

A namespace that reads as another — §7

Two namespaces a person cannot tell apart is how a supply-chain substitution starts. The check is deliberately aggressive: a false positive costs a review, a false negative costs somebody's credentials.

relations

relations/dangling

Relation to a record that is not here — §22

A composition that cannot be assembled. The reader following the edge arrives nowhere, and the claim the record makes about its own dependencies is not checkable.

relations/unparseable

Relation reference is not a reference — §22

publisher/slug, optionally pinned. A reference nobody can resolve is a sentence, not an edge.

relations/must-pin

requires or rollback_of without a version — §22

Both assert what another record does, which is only true of a version: unpinned, the claim silently follows the other author's next edit.

relations/must-not-pin

part_of or escalates_to with a version — §22

Both are structural. Pinning freezes the arrangement, so a playbook keeps pointing at last year's version of its own step while every reference still resolves.

relations/cross-publisher

part_of across a publisher boundary — §22

Declaring yourself part of somebody else's procedure is a claim about their composition, made without them. The containing record decides what it contains.

relations/self

Relation to itself — §22

A record requiring, undoing, escalating to or being part of itself asserts nothing that can be acted on, and something was meant by it — most likely a reference to the record it was copied from.

relations/cycle

A cycle in a relation kind that cannot have one — §22

A requires cycle is a dependency nobody can satisfy first; an escalates_to cycle is the handoff loop escalation exists to prevent; a part_of cycle contains itself.

resolve

resolve/bad-ref

Not a reference this catalog can read — §9

A reference is publisher/slug@semver. Guessing at a malformed one would mean fetching something the caller did not ask for, and the caller would run it.

resolve/not-found

No such record at that reference — §9

The catalog holds no record at this address. A URL here is permanent, so a miss usually means a rename — /v1/aliases.json says where a slug went — rather than a record that never existed.

resolve/hash-mismatch

The bytes are not the bytes that were signed for — §9

What arrived does not hash to what the reference pins. Running it anyway would mean running a document nobody verified, which is the one thing pinning exists to prevent.

resolve/unpinned

Reference names a version, not bytes — §14

A version follows the publisher's next edit. Everything downstream of a run — the report, the attestation, verify — binds to a content hash, so a run named by version alone is a claim about whatever that version has since become.

resolve/upstream-changed

The source document has changed since it was adapted — §10

The upstream this record was derived from no longer says what it said. The record is not wrong, but its provenance no longer describes the thing it came from, and a reader deciding whether to trust it needs to know that.

resolve/upstream-gone

The source document is no longer reachable — §10

Provenance that cannot be checked is provenance a reader has to take on faith. The record stands; what it can no longer do is prove where it came from.

run

run/gate-refused

A person refused the gate, and said why — §13

Somebody looked at the approval request and declined it. Distinct from a request that expired: an expiry is a question nobody answered, and both end the run, so the difference is carried by this event and the reason it names. An approval needs no justification — proceeding is what the runbook asked for — but a refusal is a departure from it, and the next person at this step is owed the why.

run/gate-expired

Nobody answered the gate, and the run stopped — §13

The other way a gate ends without a yes. "Proceed on timeout" is the convenient default somebody eventually adds, and it turns every gate into a delay: a question nobody answered is not permission. The run is aborted rather than continued, and this event is what separates that from a refusal, which carries a person and a reason.

run/started

The run began at the declared entry — §13

Recorded rather than assumed: a run whose beginning is not in the record cannot be replayed, and a report about it cannot be checked against the graph it claims to have followed.

run/no-entry

The runbook declares no entry step — §6

A graph with no start has no first step, so there is nothing to authorize and nowhere to begin. This is caught before anything runs rather than at the first call.

run/input-missing

A declared input was not supplied — §13

Inputs are part of what a step's command means. Starting without one means the first command is assembled from a blank, and a blank in a path is a different path.

run/input-type

An input is not the type the runbook declares — §13

A declared type is a claim the author made about what the command will receive. Coercing it here would substitute this supervisor's judgement for theirs.

run/input-undeclared

An input the runbook does not declare — §13

An input nobody declared is an input nobody reviewed, and it reaches a command. Refusing it is cheaper than working out afterwards what it interpolated into.

run/entered

The run moved to a step — §13

Every transition is on the record, because the sequence of steps actually entered is what a report is a report about — and what an approval, an expectation and a rollback are all indexed by.

run/permitted

The call was authorized for this step — §13.2

Authorization is per step, never per run: a permission granted for the union of a runbook is a permission the agent holds while doing something else entirely.

run/out-of-order-step

That step does not follow this one — §6

The graph decides where a run goes, not the agent. A jump the document does not describe is a path nobody reviewed, and every guarantee here is about the paths that were.

run/after-end

A call arrived after the run ended — §13

A run that has ended has no current step, so there is nothing to scope a permission to. A client told only 'denied' would keep proposing into a run that is over.

run/unanalyzable-command

What this command invokes cannot be determined — §12

A command whose invocations cannot be read cannot be attributed to a declared capability, so it cannot be bounded. "I could not tell" is not permission.

run/approval-required

This step stops for a person — §13.4

A destructive or irreversible step is released by a human decision, and the run holds until there is one. The gate is the point at which somebody accepts what happens next.

run/approved

A person released the gate — §13.4

Recorded with who decided, because an approval nobody can attribute is an approval that cannot be reviewed afterwards — and the agent may never be that person.

run/expectation-failed

The step did not do what it said it would — §13

A postcondition is the author's statement of what the step was for. When it does not hold, continuing means running the rest of a procedure whose premise is already false.

run/expectation-unevaluable

The postcondition could not be decided — §13

Not knowing whether a step worked is a third state, and collapsing it into either 'passed' or 'failed' invents information. It routes to a person, not to a branch.

run/unchecked-advance

Leaving a step whose result was never decided — §13

At R2 a check is left by its result, not by proposal. Advancing past an undecided postcondition is how a run reports success for a step nobody established had happened.

run/unrouted-failure

The step failed and names nowhere to go — §6

Where a failure goes is the author's decision, and it was not made. Aborting is the only honest option: continuing would be this supervisor choosing a path the document does not contain.

run/budget-exhausted

The run reached its step budget — §13

A budget is what stops a retry loop from being unbounded. Reaching it ends the run rather than continuing quietly, because the interesting fact is that it was reached.

run/wall-clock-exhausted

The run reached its time limit — §13

Time is the bound that still applies when a procedure is waiting rather than acting. A run that outlives its window is one nobody is watching any more.

run/terminal-not-reached

The run stopped somewhere that is not an ending — §6

A procedure declares its terminals, and stopping anywhere else means the run is incomplete however it looked. A report says so rather than recording it as done.

run/ended

The run ended — §13

With the outcome it ended on, because 'it finished' and 'it succeeded' are different facts and a report that conflates them cannot be aggregated into anything true.

run/adjudicated

A person decided what the supervisor could not — §13.4

An unevaluable postcondition is resolved by a human, never by the agent whose work is in question. Recorded with who decided, for the same reason an approval is.

run/nothing-to-adjudicate

There is no undecided result to rule on — §13.4

Adjudicating a run that is not waiting on one would let a decision be recorded against a step that never asked for it, which is a signature on the wrong document.

runtime

runtime/profile-too-low

The client enforces less than the runbook requires — §13.3

A procedure that outruns its supervisor is the failure the execution contract exists to prevent. This is a refusal rather than a warning, because something ranked low still gets clicked.

runtime/coverage-insufficient

The adapter cannot see every tool call — §13.3

An adapter that cannot observe a call cannot bound it, so a destructive procedure under one is unsupervised in exactly the places it matters. A proxy does not see shell access; a tool-call hook does.

runtime/risk-above-ceiling

The procedure is riskier than this client allows — §13.3

The ceiling is a standing decision about what this client may be asked to do. Raising it is a deliberate act, which is the difference between a limit and a suggestion.

runtime/autonomous-unsupervised

Autonomous execution under a client that enforces nothing — §13.3

Agent-autonomous execution needs at least R1 — an allowlist, per-step scope and approval gates. Autonomy without them is not supervision that is lenient; it is no supervision.

runtime/capability-unavailable

A capability the runbook needs is not offered — §12

A record is runnable only if every capability it declares is available, never any of them: the other reading hands an operator a procedure they can start and cannot finish, and part of a destructive procedure is a state nobody designed.

schema

schema/invalid

Does not match the published schema — §5

The schema is what a third party validates against without our code. A record that fails it has no agreed meaning.

secrets

secrets/aws-access-key

AWS access key id — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/aws-secret-key

AWS secret access key — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/github-token

GitHub token — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/slack-token

Slack token — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/private-key

Private key — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/jwt

JSON web token — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/connection-string-password

Password in a connection string — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/generic-high-entropy

High-entropy string with no recognised format — NG3

A credential in a published runbook is a credential in every cache that mirrors us. Replace it with a declared input.

secrets/private-address

Private network address — NG3

Not a credential, but a detail of your infrastructure that does not need publishing.

secrets/cloud-account-id

Cloud account identifier — NG3

Not a credential, but a fingerprint of the environment the procedure runs in.

signature

signature/invalid

Signature does not match this record — §8

The record changed after it was signed, or the signature is not this publisher's. Publishing it anyway would put the catalog's name behind a claim it checked and disbelieved.

signature/revoked

Signed with a revoked key — §8

A retired key verifies what it signed before it was retired and nothing after; a compromised key verifies nothing at all, because whoever holds it can date a forgery however they like.

signature/unverifiable

Key not published, so the signature could not be checked — §8

Not evidence of forgery: it says the key is not where the publisher said it would be. It is a warning rather than an error because a key-distribution problem is not the record's fault — and it never counts as valid, which is the half that matters.

vocabulary

vocabulary/synonym

A facet value that is a synonym of a canonical one — §4

k8s and kubernetes as two values split every list in half, and the reader who filtered by one never learns the other half existed. The record is sound; the fix is mechanical; the silence would not be.

vocabulary/unknown

A facet value that is in no vocabulary — §4

Not an error: an author with a system nobody has heard of should not be stuck, which is what keywords[] is for. But an unlisted value is not filterable, and the author is the only person who can say whether it should be.

yaml

yaml/unparseable

The document is not valid YAML — §18.3

Reported by the constructor's text view at the line it happened, under the same code the rest of the editor uses — one problem does not get two names. The text stays on screen: an editor that becomes unusable when a document does not parse is one you cannot fix a document in.