The stagebox is PRESENT and enrolled, and its preamps are nonetheless out of reach because
it is running as the REAC MASTER (reac-head-amp-control.md §11c, ruled
2026-09-14). A box on M sends no head-amp sweep and takes
none: its preamps are configured out of band, through the box's own serial port. args.node
names the reac-pw node that published the reason.
It is deliberately NOT BOX_ABSENT. The box is there — it is clocking this segment — so "the link is not established" is false, and an operator told that goes looking for a cable. This is the contract of a mode the operator chose, and the surface says so.
An actuator resolved its target but has no ADDRESS to write it at, and refuses rather than
guessing one (amendment 2026-09-07, 2026-08-05-hardware-presence-and-observed-facts.md).
args.target names what could not be addressed and args.missing the declaration that is
absent. Raised by the REAC head-amp write when the reac-pw node publishes no granted
reac.headamp.base: guessing base 0 for an S-1608 addresses its preamps 32 slots low, in
silence, which is the defect the port contract's "never parse a name to recover a fact" rule
exists to prevent.
An ordered collection was written with anything other than a permutation of its members.
A gate's KEY named a BUS as its source (keyed gates §3.2, the operator's ruling 4).
args.source is the channel key asked for. A gate keyed by a bus reads the sum its own
output is part of, so its own contribution returns, delayed, into its own detector — a
feedback loop of CONTROL. Refused by name rather than clamped to the nearest legal
channel: a write whose outcome cannot be stated is refused.
A gate's KEY would close a PAIR CYCLE — A keyed by B while B is keyed by A (keyed gates
§3.3, the operator's ruling 5: pairs, not whole-graph detection). args.channel is the
channel being written and args.source the source asked for. A cycle has no single answer
for what either gate opens on.
The declared transition on a row that carries a ConfirmGate arrived with no
confirm: true while the gate holds (row grammar, "Confirm: the eighth clause" and "the
trigger is a declared transition", issues #738, #776). Over a preview: args.count is how
many entries it lists and args.fields names them, comma-joined in the preview's order, and
the fault answer carries the preview row's state as preview. With no ask: args.count is
1, args.fields names the transition's field, and no preview rides. Raised by the
registry — the one door — so a browser, an OSC sender and an MCP caller are all refused the
same way and answer with the same argument.
A hosted plugin would sit at a declared point the lane cannot RUN it at (ruling 2026-09-02,
2026-08-23-tap-points-per-template.md). args.at is the point asked for and args.native
the places a plugin runs where it is declared, comma-joined in signal order. Raised by the
chain processor door for a plugin racked at such a point or a racked slot moved to one, and
by the send row's tap door on a strip that still holds such a slot — both say the same on
OPTIONS. Without it a plugin racked behind the fader was threaded at the head and every send
capture on the strip was refused downstream, where no client could see why.
A plugin with more audio output legs than the strip has legs is racked on that strip (ruling
2026-09-02, 2026-08-23-tap-points-per-template.md). args.uri is the plugin asked for,
args.legs its audio output count and args.width the strip's width. Raised by the rack
door, and the same code greys the plugin on the rack control's OPTIONS. Without it a stereo
plugin's two legs landed in a mono strip's ONE input port and PipeWire summed them: MAIN
moved 6.02 dB with no control touched (job-lv2-insert-width-audio.test.ts).
A write would put a plugin into the signal path on a console whose PLUGIN HOST is declared
unavailable (ruling 2026-09-02, 2026-07-15-plugin-catalog-tiered-packaging.md). args.host
is the host program the console would need. Raised by the rack door, the rack slot's swap and
the chain processor's plugin door, and the same code greys all three on OPTIONS. Un-racking
is never refused: an empty rack and a cleared slot are the way out when a live host dies.
Without it the conformance desk answered a rack PATCH 200 { ok: true } with the rack still
empty — a control that claims to reach audio and reaches nothing.
A projection's engine mirror is not wired at all — the state is held and broadcast only.
The engine door a projection needs has not been built yet (console has not started).
A projection needs a device graph and this console was built without one.
A native-mixer write returned a rejection rather than throwing.
A native-mixer write threw.
Releasing an exclusive latch reaches no audio by design — there is nothing to re-drive.
A SELECTIVE revert was refused because the field no longer reads what the entry landed on:
somebody moved it since. The query-and-compare of 2026-09-01-undo-history.md §6, and the
refusal IS the offer — args carry field, expected (what the entry landed on), found
(what is there now), entry, and where the ring can name it, overriddenBy /
overriddenSource (the later entry that moved it, and who wrote it). Firing again with
override: true performs the jump-back. Never a silent cascade: the operator decides, and
exactly one field is written either way.
A channel was patched to a SECOND physical input. Summing sources IS what a bus is, so a
summed channel would be an undeclared second summing primitive — operator ruling
2026-08-25, 2026-08-07-one-summing-bus.md §3c. SOFT sources are not counted: an
application stream owns no preamp, and a strip carrying a browser and a media player is
the console's playback channel, not a stagebox patch.
A patch leg named a BOX INPUT the desk cannot address: no box carries that boxId on this
console, or the box carries it and publishes no port for that input (it is absent, or the
input is past its width). args.box and args.input are what was asked for, args.at and
args.key where in the written array it sat.
Refused rather than resolved to the nearest thing: naming a port and hoping the roster had
not moved is exactly what put channels 9-40 on the wrong preamps when two boxes traded
segments (an internal spec). One code for both
cases because the client's next move is the same — read the roster and ask again — and
because an absent box publishes no ports at all, so the console cannot always tell them
apart without a second statement of the box's width.
Applying a STORED item to the live console failed for a reason not covered above — a scene
recall, a session or patch load, a channel config. One code for all four because it is one
fact ("the apply broke, the reason is in the log, not on the wire"); the entity's own path
and the id arg say which item, so a second spelling would carry nothing extra.
SIP guard (#192): mode: 'sip' refused because the guard is not armed in Setup. The guard's
second step — the write's own confirm: true — is the registry's confirm gate on /cue
and refuses CONFIRM_REQUIRED like every other gated row.
An insert rack was refused by the destination-suitability judgement (issue #339): the
bus this chain lands on cannot afford its latency and its role enforces the refusal.
args.finding carries the judgement's own message code, which says which and why.
A clipboard part cannot land on this target: the channel does not carry the facts the part
is made of (sends on a bus, eq on a DCA). args.part names the part and args.facts
the missing facts, comma-joined, so the surface can say WHICH knob is not there rather than
only that something was refused. Never a silent drop — see channel-clipboard-carriage.ts.
An operation's declared PARAMETER was written without firing the run. A stored argument that
takes effect at some later fire is the ambiguous success the house forbids, so the operation
mold accepts parameters only alongside running: true. args.field names the parameter.
An operation was fired without one of its DECLARED parameters. Every declared parameter is
required on the fire: an operation that ran against a silently-defaulted argument would be
a run nobody asked for. args.field names the missing parameter.
A console allocation was asked to SHRINK while the desk is running. The design fixes N up
front — every summing bus is sized to N so every input can reach every bus with no mid-show
resize — and the engine's build door only ever adds, so accepting a smaller number would
store a shape the console does not have. Growing is fine and is the ordinary case; making the
desk smaller happens where it can be rebuilt: at boot, or on a session load. args.held
carries what the console is holding, so a surface can say what it refused to go below.
An allocation was asked to shrink a pool that STILL HAS SOMETHING ATTACHED to its top —
three matrices where the show addresses matrix/5. Distinct from NO_MID_SHOW_SHRINK,
which refuses ANY live shrink whatever is attached: this one guards the RESTART-TIME shape,
where shrinking is otherwise legal, and refuses only the part that would ORPHAN the
operator's own work. The way through is manual unassignment first (operator ruling
2026-09-14: losing membership stays a separate, visible act, never a side effect of
accepting an allocation). args.pool names the pool, args.holds its floor and
args.using the addresses to unassign, so a surface can say exactly what to clear.
A count was asked to exceed the active console appliance's cap for that pool. 2026-09-15:
before this code existed, PATCH /console/allocation {inputChannels: 96} against a profile
capped at 64 was ACCEPTED — nothing on the live write door compared against the profile —
the session recorded it, and only the NEXT BOOT's own profile check caught it, by refusing
to start. A control refuses visibly, never succeeds ambiguously: this is that refusal, at
accept time. args.pool names the pool (inputChannels, or a bus type), args.max its cap.
A gesture that would REPLACE the live show was asked for while the console carries changes
nobody has written to a NAMED session (2026-09-16-new-session.md §5). The autosaves do not
count: the live autosave is the engine's own restore point, not a show the operator named —
which is the whole reason this refusal exists. args.session names the show that would be
lost, so a surface can say WHICH one rather than only that something would be. The way
through is to save, or to say so explicitly (discardUnsaved: true) — never a silent
overwrite of work the operator can no longer get back.
This entity declares no DELETE door — its items are not removable, by design.
This entity declares no POST door — its items are not created through the wire.
A POST named an id the store ALREADY holds. Distinct from a refused patch: the caller
asked to bring something into existence and it is already there, so silently replacing it
would turn a create into an unannounced overwrite of whatever the desk was holding.
args.id names the collision. The way through is the PATCH door on that instance.
A POST body left out a field the created item cannot exist without — a source with no
adapter names no physical input. A create is WHOLE by construction (there is no prior state
to merge into), so a defaulted field would be the console inventing a fact the operator did
not state. args.field names the first one missing.
Persisting a new stored item failed (the store threw: disk, permissions, a bad name).
The address names an item the ENGINE owns, not the operator's library — the live/pre-load
autosave ids (SessionStore's LIVE_AUTOSAVE_ID/PRELOAD_AUTOSAVE_ID). A save-into/overwrite
door refuses these rather than letting an operator's "Save" silently repoint the engine's own
restore points.
Removing a stored item failed (the store threw). The item may still be there.
A POST door's creation failed (the door threw). 'SAVE_FAILED''s counterpart for a door that mints no FILE: a direct path opens a PipeWire node and links real ports, and when that throws the answer is "nothing was created", never a created item nobody can find.
The state is real but this channel has no native stage to carry it. The input strips and the MAIN master stage have one; an aux, a matrix or a time-based FX insert on the master does not, and says so rather than reporting an effect the node cannot have.
A bus was asked to route nowhere and it DECLARES outputRequired — the operator's "do not
allow self-erasing" (2026-08-06). A per-bus PROPERTY, never a rule about a kind: the default
is that any bus, MAIN included, may be routed nowhere. args.bus names which one refused,
so the surface can say it where the gesture happened rather than snapping a cell back with
no reason. Emptying must never answer applied: true and change nothing at all.
A ROSTER PATCH does not state a set this roster can hold. Every member-addressed family
serves its membership as the collection row's own value, and this is the one refusal for a
body that is not a statement of it — with the difference NAMED (args.missing /
args.extra / args.duplicate) rather than silently adopted as a second census.
The two rosters it serves ask different things of a list, and both are this code:
/channel — order is the value, the SET is the console allocation's, so a list that
invents a strip or leaves one out is a reordering that isn't one;/patch/output/{kind}/{n} — the SET is the operator's (dropping a leg unpatches the
mix), so leaving one out is a legal request; naming an ordinal the mix does not hold
(args.extra), or naming one twice (args.duplicate), is not.A client wrote clipped: true — or a non-empty latched list on the collection — to a clip
latch. Only the engine's own capture may claim an over (2026-08-29-clip-latch.md §2); the
one write a client owns is the clear.
A mix already holds its one destination and a SECOND was asked for (POST to
/patch/output/{kind}/{n}). The operator's ruling (#86): "this is something we should start
FORBIDDING, this is what matrices are for" — a matrix output is a strip, carrying its own
delay, trim, EQ, fader and name, so fanning a bus to two places builds a second nameless
routing tier that does the same job worse. args.use names the way through ('matrix'),
because a refusal that only says no leaves the operator with a gesture and no answer.
args.max is the cap and args.bus the mix that refused. Accepting a second destination
stores it and creates no native route, so the write reads as applied and moves no audio (#85).
A destination was asked to route NO LEG at all — every role written null on
/patch/output/{kind}/{n}/leg/{legId}, or a POST body naming no port. A destination with
no leg is not a smaller destination, it is the ABSENCE of one, and the absence has its own
door: DELETE the leg. Accepting it would leave the mix holding a destination that feeds
nothing, indistinguishable on the wire from a patch half made.
The mix's destination is LOCKED and the write would move it or take it away (operator
ruling, 2026-09-01: a gig protection, desk state, persisted with the session because it
must survive a restart). args.bus names the mix, and args.unlock names the field whose
write lifts it — a refusal that only says no leaves the operator with a gesture and no way
through, and the way through here is one PATCH on this same row.
WHAT IT GUARDS IS THE PLUMBING, NOT THE MIXING. The lock's purpose is that the destination
does not MOVE and does not VANISH mid-show, so it refuses the port writes (L / R), the
roster shrink and the leg DELETE. It does NOT refuse trimDb, delayMs, monoFold or
mute: those are the desk's tuning of a destination that is going nowhere. Two of them
matter enough to state — delayMs is what Smart Alignment's APPLY writes through this very
row, so a lock that froze it would silently disable the alignment the operator locked the
destination in order to keep; and mute is the one gesture that must never need paperwork,
because an operator killing the PA in an emergency cannot be told to unlock something first.
monoFold: true was asked of a destination whose legs land on TWO DIFFERENT ports, and a
fold has one port by definition. Folding it would have to abandon one of them, silently —
the refusal exists because a write that delivers less than it was asked for and says nothing
is the defect this desk keeps paying for. args.ports names the two it found. The way
through is one PATCH: state the port on both roles ({L:p, R:p, monoFold:true}), or drop a
role first. Ruled 2026-09-07 (per-leg output spec, amendment 2026-09-07b).
A C (centre) output leg was written on a bus whose import('./bus-format.js').BusFormat
is not 'lcr' — a stereo bus has no discrete centre speaker, so the role is refused rather
than silently stored on a port nothing plays (2026-09-08-lcr-mains.md §2.1/§4, task #176).
The way through is a PATCH that sets the bus's own format to 'lcr' first.
A per-SIDE leg delay (delayMsL / delayMsR / delayMsC) was written on a side that has no
PORT OF ITS OWN to arrive at — the leg does not route that role at all, or the destination
FOLDS and that role shares an earlier role's port. Flight time is a fact of where a box
stands; a side with no box has none, and storing a figure there would change a number and
move no loudspeaker (the /rme/totalmix defect). args.role names the side. The way through
is one PATCH that gives the role its own port. Ruled 2026-09-09 (per-leg output spec,
amendment 2026-09-09, issue #845).
format: 'lcr' was asked of a bus whose kind the native seam does not widen yet — a group
bus in phase 1 (#176, 2026-09-08-lcr-mains.md §3's recorded scope cut: mixerSetBusFormat
only ever touches MAIN's main_C port; there is no generic per-bus format array). The row
still exists on that bus (so a client can render it, disabled) and reads 'stereo' forever.
format: 'lcr' was asked of a bus on an appliance whose profile does not offer it for that
bus type (#176, archive §8 — a Midas PRO's phase-1 stereo-only ceiling here, distinct from
'FORMAT_NATIVE_UNSUPPORTED': the native seam COULD widen this bus, the ROLAND
appliance proves it, but THIS appliance's own declared travel refuses the value).
The path variables do not NAME an instance of this entity at all — as distinct from
'NO_INSTANCE', which is "this console does not hold that one".
/patch/output/monitor/1 is the worked case: monitor is not a channel kind, so no
console could ever hold it, while /patch/output/aux/99 names a real kind at an index
this desk lacks. args carries the variables exactly as given, so a client can say WHICH
segment named nothing rather than only that something did.
It exists because a bare no-such-instance carrying no code is invisible: a surface only
reports a refusal that HAS one, so patching a destination the model has no row for stores
nothing, links nothing, and refuses nothing the operator can see.
Monitor mode B (#191) was asked for and could not be established: the takeover crossfade is a flag on a MAIN out_route, and MAIN is not fanned out to the sink the monitor destination lands on (or the only match is MAIN's PRIMARY, the house, which may never be a monitor). The way through is in the operator's hands and in the same surface — route MAIN to that sink as an extra destination — which is why this refuses rather than recording a flag that drives nothing. A desk that cannot answer the question is never refused on it.
DELETE /safety/loop (break the routing loop) found no operator-made source patch on the
ring to cut: everything on it is console structure — a strip's head → fader → bus path, a
bus master's chain — and the desk does not dismantle its own strips to open a ring. It says
so instead of silently doing nothing, which would read as success on a desk still about to
howl.
The plugin-analysis sweep gate refused a /measurement/run fire (issue #342): the engine
is processing audio, no measurable rate is known, or a sweep is already in flight.
args.finding carries the gate's own message code (measurement.engine-live /
measurement.no-rates / measurement.already-running) — the SAME code
/measurement/plan.refusal previews before any fire — with the finding's numeric params
(pct) flattened beside it, so a surface renders the preview and the refusal through one
catalog entry. The INSERT_REFUSED shape: one closed refusal word wrapping a coded
message, never a refusal-code mint per gate clause.
The record transport refused a start (2026-07-16-recording-vsc.md §2.3): a take is already
running, no channel would be captured, there is no engine, or the disk cannot hold the
take's first minutes. args.finding carries the gate's own message code
(record.already-running / record.nothing-armed / record.no-engine /
record.no-space), with the space finding's byte counts (needBytes, freeBytes)
flattened beside it so a surface renders "needs 14 GB, has 3" rather than "the disk is
full". The INSERT_REFUSED shape: one closed refusal word wrapping a coded message, never
a refusal-code mint per gate clause.
The virtual soundcheck refused a load, an engagement or a transport move
(2026-07-16-recording-vsc.md §3): no take is loaded, the take carries no track for this
channel, the take's rate is not the graph's, a take is being recorded, the id names nothing,
the audio will not play, or a play would run with no channel listening (§3.4). args.finding carries the gate's own message code (vsc.no-take
/ vsc.no-track / vsc.rate-mismatch / vsc.recording / vsc.no-such-take /
vsc.take-unplayable / vsc.no-engine / vsc.not-engaged), with the rate finding's two numbers (takeRate,
graphRate) flattened beside it so a surface renders "the take is 48 kHz, the graph is 96"
rather than "the rates do not match". The INSERT_REFUSED shape: one closed refusal word
wrapping a coded message, never a refusal-code mint per gate clause.
A stagebox entry that HOLDS a recognition key was written an empty one. Binding a key
(StageboxRegistry.bindKey) and absorbing whatever entry held it is the one transition the
design describes (an internal spec);
surrendering one is not, so the write is refused rather than silently accepted and ignored —
an operator asking to unbind a box deserves a coded no, not a claimed success that moved
nothing. Writing '' onto an entry that already holds NO key is unaffected: that stays a
genuine no-op, since it changes nothing and claims nothing.
A bound entry was asked to take a key from a DIFFERENT transport. The identity spec
(2026-08-22) rules it: an entry declaring an s1608 cannot take a usb: key — its model
fixes sixteen XLR inputs and the metal answering has twelve of three kinds, so the bind
would leave a patch addressing ports that do not exist, silently. The check is transport
equality; model equality is NOT required, because replacing a dead S-0808 with an S-1608
is a legitimate repair.
/reac/segment/{name}'s rate was asserted outside that segment's PUBLISHED drivable
subset (reac.rate.drivable) — the closed per-protocol list (44100/48000/96000) is
UNKNOWN_ENUM's business, but a value ON that list this NIC/clock still cannot pace is a
different fact, and OUT_OF_RANGE is the wrong shape for a discrete published SET rather
than a span (an internal spec). args.value names
what was asked for, args.drivable the published subset it was refused against.
A swap onto a channel's prepared spare was refused because the spare's PORT is not in the
live graph — the stagebox it hangs off is unplugged, or the source stream is stopped
(2026-07-30-southbound-actuator-contract.md §10). args.port names it.
Its own code, and refused rather than accepted: the spare exists to be the fix when the primary dies, so re-pointing a live channel at a socket that carries nothing would trade a dead microphone for a dead patch and report success. The REVERSE gesture is never refused this way — the primary is usually absent precisely because it is what failed.
An offline render of a take was refused. ONE word over six gates, with the gate's own
coded finding in args.finding — no engine, no renderable track, no disk, a render
already running, a take being captured, or a soundcheck replaying. A code per clause
would put the vocabulary in the refusal instead of in the message catalogue, where an
operator's language lives.
An export of a take's MAIN print was refused. ONE word over six gates, with the gate's own
coded finding in args.finding, for RENDER_REFUSED's reason: no library, no MAIN capture,
an empty or unreadable capture, no disk, or an export already running.
A room-mode EQ proposal was asked to APPLY while the output's own FBS arming
(/channel/{kind}/{index}/fbs) is not live (2026-09-08-room-analysis.md §9 ruling 1).
Room Analysis mints no switch of its own — it reads the SAME per-channel mode FBS already
carries, so off/ringout both read as MONITOR here: propose and mark, apply nothing.
args.mode names the mode actually found.
An ORDERED list named the same member twice. Refused rather than deduped, for the same
reason enumSet refuses an unknown member: a list the desk silently shortens reads back
different from what was written, and the operator learns nothing about which rule did it.
args.got is the repeated member, args.at the index the repeat sat at.
A stage-order write named a stage this channel KIND does not have
(2026-09-15-channel-stage-order.md §4). args.stage and args.kind say which. The
CONTRACT declares a kind's stage set, so this is answered from contractDeclares and never
from a list kept beside the row.
A stage-order write LEFT OUT a stage this kind has. Refused rather than appended, though
omx_order_normalize would append it at the native boundary: a list accepted and echoed
back longer than it was written teaches the operator nothing about which desk law rewrote
their order — the silent-clamp false signal, at a door.
A DELETE /stagebox/{boxId} named an entry that is answering on the wire RIGHT NOW
(stagebox-identity spec + the destructive-remove ruling, 2026-09-16). Forgetting a box is
for an entry this rig will never see again — a ghost the operator wants gone — never for
one that is live: deleting a present box's identity would strand its patch on metal that is
still plugged in, silently, the moment the desk next reads the wire. Unplug it, or wait for
it to go absent, then forget it.
Why a write (or a field) is refused — a CLOSED union. The wire carries the code and args; one formatter renders prose at the log edge; clients localize from the code. Extending the vocabulary is a deliberate one-line commit here.