:: vesl-nockup beta is currently live
Skip to content

Effect Catalog ​

This page enumerates every effect head tag and its full payload shape across the shipped grafts. Each section is one graft, with two tables: success effects (cell shapes) and error effects (verbatim message strings from the Hoon source). For the teaching version of how effects are emitted, see Kernel → Domain Causes. For Rust-side decoding patterns (the loobean-inversion footgun, cell payload extraction, unit returns), see Hull → Decoding Effect Payloads.

The matching read surface is Peek Catalog.

Typed Rust mapping

Every effect class on this page has a matching variant on a typed per-graft outcome enum the test harness ships. %<graft>-error msg=@t decodes to <Graft>Outcome::Error { msg }, %<graft>-denied reason=@t to Denied { reason }, and each typed rejection (e.g. %settle-register-rejected) to a named struct variant. The kernel's success effects collapse to Accepted { effect_tags }. See Harness → Typed Per-Graft Methods for the generated surface; tests match on the variant via outcome.as_<graft>_outcome().


settle-graft ​

Success effects:

EffectPayload shapeEmitted when
%settle-registered[hull=@ root=@]%settle-register lands; hull is now registered against root.
%settle-notednote=[id=@ hull=@ root=@ state=[%settled ~]]%settle-note lands and the verify gate accepted the payload.
%settle-verifiedok=?%settle-verify runs (a pure preflight; no state transition). ok is loobean — atom 0 = passed, atom 1 = failed.
%settle-epoch-rotated[old-epoch=@ new-epoch=@]Emitted alongside %settle-noted when settle-count hits epoch-cap (1M settles per epoch) and the settled set rotates.

Typed rejections (cell payload, not a %settle-error cord):

EffectPayload shapeEmitted when
%settle-register-rejected[hull=@ existing-root=@]%settle-register against a hull that already has a root (registration is one-shot per hull). existing-root is the currently-registered root atom — callers can pattern-match the typed tag instead of parsing the legacy %settle-error cord. (Audit L-09; post-settle-graft 0.2.0.)

Errors (all emit [%settle-error msg=@t]):

msg cordEmitted when
'settle-graft: registered map at capacity'~(wyt by registered) reached the 10M-entry cap.
'settle-graft: malformed payload'%settle-note or %settle-verify payload atom failed to cue (mule-wrapped at the boundary).
'settle-graft: root not registered'Payload references a hull that has no registered root.
'settle-graft: root mismatch'Payload's expected-root doesn't match the registered root for the hull.
'settle-graft: note root does not match expected root'Payload's note.root doesn't match expected-root (cross-check H-04).
'settle-graft: note already settled'note.id is already in the current-epoch settled set.
'settle-graft: note already settled (prior epoch)'note.id is in prior-settled — the rotated lookback set.
'settle-graft: verify gate crashed'Verify gate panicked inside mule (caught crash, vs. a clean ?> deterministic Exit).

A clean ?> rejection from the gate emits zero effects, not %settle-error; see Common Pitfalls → Distinguishing Denial Paths.

mint-graft ​

Success effects:

EffectPayload shapeEmitted when
%mint-committed[hull=@ root=@]%mint-commit lands.

Errors (all emit [%mint-error msg=@t]):

msg cordEmitted when
'mint-graft: hull already committed'%mint-commit against a hull that already has a root (commitments are one-shot).
'mint-graft: commits map at capacity'~(wyt by commits) reached the 10M-entry cap.

guard-graft ​

Success effects:

EffectPayload shapeEmitted when
%guard-registered[hull=@ root=@]%guard-register lands.
%guard-checked[hull=@ ok=?]%guard-check runs; ok is loobean — atom 0 = hash-leaf(data) == registered-root, atom 1 = mismatch.

Errors (all emit [%guard-error msg=@t]):

msg cordEmitted when
'guard-graft: hull already registered'%guard-register re-applied to a registered hull.
'guard-graft: roots map at capacity'~(wyt by roots) reached the 10M-entry cap.
'guard-graft: hull not registered'%guard-check against a hull with no registered root.

forge-graft ​

Success effects:

EffectPayload shapeEmitted when
%forge-proved[hull=@ note-id=@ proof=*]%forge-prove succeeded; proof is the opaque STARK proof noun bound to hull and root = hash-leaf(data) via the Fiat-Shamir transcript.

Errors (all emit [%forge-error msg=@t]):

msg cordEmitted when
'forge-graft: prove-computation crashed'The prover bombed inside mule (e.g. malformed data, internal ;; rejection).

kv-graft ​

Success effects:

EffectPayload shapeEmitted when
%kv-storedkey=@t%kv-set lands (overwrite-on-existing; bypasses the capacity cap on overwrite).
%kv-deletedkey=@t%kv-delete lands. Always emits, even for missing keys (noop is silent on the state side but visible on the effect side).

Errors (all emit [%kv-error msg=@t]):

msg cordEmitted when
'kv-graft: store map at capacity'~(wyt by store) reached the 10M-entry cap on a new-key insertion.

counter-graft ​

Success effects:

EffectPayload shapeEmitted when
%counter-incremented[name=@t value=@ud]%counter-increment advanced name. value is the post-increment value.
%counter-resetname=@t%counter-reset set name to 0 (init-on-touch).
%counter-set[name=@t value=@ud]%counter-set overwrote name. Note the head-tag collision: %counter-set (past-participle) and the cause %counter-set (imperative) read identically; spec keeps them.

Errors (all emit [%counter-error msg=@t]):

msg cordEmitted when
'counter-graft: counter saturated at 2^64'%counter-increment would push the counter past 2^64 - 1. State unchanged; caller must %counter-reset first.
'counter-graft: counters map at capacity'New-name insertion would push ~(wyt by counters) past the 10M cap.

queue-graft ​

Success effects:

EffectPayload shapeEmitted when
%queue-pushedid=@ud%queue-push appended; id is the monotonic id assigned.
%queue-poppedjob=(unit [id=@ud body=*])%queue-pop ran. job=~ if the queue was empty; job=[~ [id body]] if a job was dequeued.
%queue-cleared~%queue-clear ran (idempotent; emits even for already-empty queues).

Errors (all emit [%queue-error msg=@t]):

msg cordEmitted when
'queue-graft: malformed payload'The jammed body atom failed to cue (C1 mule-wrap boundary).
'queue-graft: pending list at capacity'(lent pending) reached the 10M-entry cap.

rbac-graft ​

Success effects:

EffectPayload shapeEmitted when
%rbac-granted[pubkey=@ added=(list @t)]%rbac-grant ran. added is the set difference (asked − held) — only the newly-added perms, not the full post-state.
%rbac-revoked[pubkey=@ removed=(list @t)]%rbac-revoke ran. removed is the intersection (asked ∩ held) — only the perms that were actually present and got dropped.

Errors (all emit [%rbac-error msg=@t]):

msg cordEmitted when
'rbac-graft: roles map at capacity'New-pubkey insertion would push ~(wyt by roles) past the 10M outer cap.
'rbac-graft: perms-per-role at capacity'The post-grant perms set would exceed the 1000-perm inner cap. Applies to overwrites too, not just new pubkeys.

Two-level capacity is load-bearing — the inner cap stops a single attacker pubkey from fanning out perms unbounded inside one row. See Library Catalog → rbac-graft.

registry-graft ​

Success effects:

EffectPayload shapeEmitted when
%registry-storedkey=@%registry-put lands (strict create — errors on duplicate key, not overwrite).
%registry-updated[key=@ old=* new=*]%registry-update lands. Both old and new records surface in the effect, so audit-style callers don't need a peek round-trip.
%registry-deletedkey=@%registry-del lands (strict — errors on missing key).

Errors (all emit [%registry-error msg=@t]):

msg cordEmitted when
'registry-graft: key already present'%registry-put against an existing key. Use %registry-update to overwrite.
'registry-graft: entries map at capacity'~(wyt by entries) reached the 10M-entry cap.
'registry-graft: malformed payload'The jammed record atom failed to cue (both %registry-put and %registry-update).
'registry-graft: key not present; use put'%registry-update against a missing key.
'registry-graft: key not present'%registry-del against a missing key.

validate-graft ​

Success effects:

EffectPayload shapeEmitted when
%validate-rules-installed[cause-tag=@ta count=@ud]%validate-init lands. count is the number of rules in the installed list (post-replace).
%validate-rules-clearedcause-tag=@ta%validate-clear drops the rules for cause-tag. Idempotent.
%validate-rejected[cause-tag=@ta reason=@t]The poke-prelude block short-circuited a poke before the ?- switch. State is untouched. Fires for any poke whose cause-tag has installed rules and at least one rule fails.

Errors (all emit [%validate-error msg=@t]):

msg cordEmitted when
'validate-graft: too many rules per cause'(lent rules) exceeds the 64-rule per-cause cap.
'validate-graft: rules map at capacity'New cause-tag insertion would push ~(wyt by state) past the 10k cap.

The %validate-rejected effect is the prelude-driven denial signal; see Grafts → Inject → Cause Dispatch Semantics for prelude semantics.

log-graft ​

Success effects:

EffectPayload shapeEmitted when
%log-appendedseq=@ud%log-append prepended an entry. seq is the monotonic id assigned. Eviction of an oldest entry past the 100k retention cap is silent (no error emitted).

Errors (all emit [%log-error msg=@t]):

msg cordEmitted when
'log-graft: malformed payload'The jammed data atom failed to cue.

clock-graft ​

Success effects:

EffectPayload shapeEmitted when
%clock-tickednow=@da%clock-tick advanced the counter by 1. now is the post-tick value cast as @da.

Errors ([%clock-error msg=@t]):

The %clock-error variant is declared in the effect union but no current arm emits it — reserved for future config-validation needs. %clock-tick has no payload to cue and no capacity to exceed, so there is no v0.1 failure path.

batch-graft ​

Success effects:

EffectPayload shapeEmitted when
%batch-initializedthreshold=@ud%batch-init set the count trigger. threshold=0 disables auto-flush.
%batch-addedid=@ud%batch-add accepted an intent and assigned id.
%batch-flushed[bundle=(list *) count=@ud]The buffer drained. Two triggers: (a) %batch-add pushed the pending length to >= threshold (auto-flush, emitted alongside the %batch-added); (b) %batch-flush was poked manually (always emits, even for empty buffers — observers can mark the boundary).

Errors (all emit [%batch-error msg=@t]):

msg cordEmitted when
'batch-graft: threshold exceeds pending cap'%batch-init threshold=X with X > 10_000_000 — a threshold higher than the buffer cap can never fire.
'batch-graft: malformed intent payload'The jammed intent atom failed to cue (C1 mule-wrap boundary).
'batch-graft: pending list at capacity'(lent pending) reached the 10M-entry cap before threshold could trigger.

intent-graft ​

intent-graft is the family-5 placeholder. The effect union reserves %intent-declared id=@ hull=@, %intent-matched id=@, %intent-cancelled id=@, %intent-expired id=@, and %intent-error msg=@t, but every poke-arm crashes with ~| %intent-graft-placeholder !!. Composing the graft is supported (so callers don't trip up on the namespace); driving it is not. Watch the hoon/lib/intent-graft.hoon header for when upstream lands the canonical primitive.


See Also