openmixer — generated API reference
    Preparing search index...

    Type Alias RefusalCode

    RefusalCode:
        | "UNKNOWN_FIELD"
        | "READ_ONLY"
        | "BAD_TYPE"
        | "NOT_FINITE"
        | "OUT_OF_RANGE"
        | "UNKNOWN_ENUM"
        | "NO_INSTANCE"
        | "NO_BACKEND"
        | "OWNED_BY_PEER"
        | "HELD_BY_LATCH"
        | "BOX_ABSENT"
        | "BOX_MASTER"
        | "UNKNOWN_PARAMS"
        | "NOT_LANDED"
        | "NO_WIRE_ADDRESS"
        | "NOT_A_PERMUTATION"
        | "KEY_SOURCE_IS_BUS"
        | "KEY_CYCLE"
        | "CONFIRM_REQUIRED"
        | "INSERT_POINT_UNREALISED"
        | "INSERT_WIDTH_MISMATCH"
        | "PLUGIN_HOST_ABSENT"
        | "NO_ENGINE_MIRROR"
        | "ENGINE_NOT_STARTED"
        | "NO_DEVICE_GRAPH"
        | "NATIVE_REFUSED"
        | "NATIVE_ERROR"
        | "LATCH_RELEASE_NOOP"
        | "HISTORY_MOVED"
        | "ONE_PHYSICAL_INPUT"
        | "BOX_INPUT_UNRESOLVED"
        | "RECALL_FAILED"
        | "SIP_DISARMED"
        | "INSERT_REFUSED"
        | "PART_NOT_CARRIED"
        | "PARAM_WITHOUT_FIRE"
        | "PARAM_MISSING"
        | "NO_MID_SHOW_SHRINK"
        | "POOL_IN_USE"
        | "EXCEEDS_PROFILE_CAP"
        | "UNSAVED_CHANGES"
        | "NOT_REMOVABLE"
        | "NOT_CREATABLE"
        | "ALREADY_EXISTS"
        | "MISSING_FIELD"
        | "SAVE_FAILED"
        | "ENGINE_OWNED"
        | "DELETE_FAILED"
        | "CREATE_FAILED"
        | "NO_NATIVE_STAGE"
        | "OUTPUT_REQUIRED"
        | "ROSTER_MISMATCH"
        | "CLIP_IS_MEASURED"
        | "ONE_DESTINATION"
        | "NO_LEG"
        | "OUTPUT_LOCKED"
        | "FOLD_TWO_PORTS"
        | "BUS_FORMAT_ROLE_REFUSED"
        | "LEG_SIDE_NO_PORT"
        | "FORMAT_NATIVE_UNSUPPORTED"
        | "FORMAT_NOT_ON_APPLIANCE"
        | "NOT_ADDRESSABLE"
        | "NO_MONITOR_TAKEOVER_ROUTE"
        | "NO_CUTTABLE_EDGE"
        | "SWEEP_REFUSED"
        | "RECORD_REFUSED"
        | "VSC_REFUSED"
        | "NO_KEY_SURRENDER"
        | "CROSS_TRANSPORT_BIND"
        | "RATE_NOT_DRIVABLE"
        | "SPARE_PORT_ABSENT"
        | "RENDER_REFUSED"
        | "EXPORT_REFUSED"
        | "MODE_NOT_LIVE"
        | "DUPLICATE_MEMBER"
        | "STAGE_NOT_ON_KIND"
        | "STAGE_MISSING"
        | "BOX_PRESENT"

    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.

    Type Declaration

    • "UNKNOWN_FIELD"
    • "READ_ONLY"
    • "BAD_TYPE"
    • "NOT_FINITE"
    • "OUT_OF_RANGE"
    • "UNKNOWN_ENUM"
    • "NO_INSTANCE"
    • "NO_BACKEND"
    • "OWNED_BY_PEER"
    • "HELD_BY_LATCH"
    • "BOX_ABSENT"
    • "BOX_MASTER"

      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.

    • "UNKNOWN_PARAMS"
    • "NOT_LANDED"
    • "NO_WIRE_ADDRESS"

      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.

    • "NOT_A_PERMUTATION"

      An ordered collection was written with anything other than a permutation of its members.

    • "KEY_SOURCE_IS_BUS"

      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.

    • "KEY_CYCLE"

      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.

    • "CONFIRM_REQUIRED"

      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.

    • "INSERT_POINT_UNREALISED"

      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.

    • "INSERT_WIDTH_MISMATCH"

      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).

    • "PLUGIN_HOST_ABSENT"

      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.

    • "NO_ENGINE_MIRROR"

      A projection's engine mirror is not wired at all — the state is held and broadcast only.

    • "ENGINE_NOT_STARTED"

      The engine door a projection needs has not been built yet (console has not started).

    • "NO_DEVICE_GRAPH"

      A projection needs a device graph and this console was built without one.

    • "NATIVE_REFUSED"

      A native-mixer write returned a rejection rather than throwing.

    • "NATIVE_ERROR"

      A native-mixer write threw.

    • "LATCH_RELEASE_NOOP"

      Releasing an exclusive latch reaches no audio by design — there is nothing to re-drive.

    • "HISTORY_MOVED"

      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.

    • "ONE_PHYSICAL_INPUT"

      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.

    • "BOX_INPUT_UNRESOLVED"

      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.

    • "RECALL_FAILED"

      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_DISARMED"

      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.

    • "INSERT_REFUSED"

      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.

    • "PART_NOT_CARRIED"

      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.

    • "PARAM_WITHOUT_FIRE"

      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.

    • "PARAM_MISSING"

      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.

    • "NO_MID_SHOW_SHRINK"

      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.

    • "POOL_IN_USE"

      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.

    • "EXCEEDS_PROFILE_CAP"

      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.

    • "UNSAVED_CHANGES"

      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.

    • "NOT_REMOVABLE"

      This entity declares no DELETE door — its items are not removable, by design.

    • "NOT_CREATABLE"

      This entity declares no POST door — its items are not created through the wire.

    • "ALREADY_EXISTS"

      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.

    • "MISSING_FIELD"

      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.

    • "SAVE_FAILED"

      Persisting a new stored item failed (the store threw: disk, permissions, a bad name).

    • "ENGINE_OWNED"

      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.

    • "DELETE_FAILED"

      Removing a stored item failed (the store threw). The item may still be there.

    • "CREATE_FAILED"

      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.

    • "NO_NATIVE_STAGE"

      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.

    • "OUTPUT_REQUIRED"

      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.

    • "ROSTER_MISMATCH"

      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.
    • "CLIP_IS_MEASURED"

      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.

    • "ONE_DESTINATION"

      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).

    • "NO_LEG"

      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.

    • "OUTPUT_LOCKED"

      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.

    • "FOLD_TWO_PORTS"

      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).

    • "BUS_FORMAT_ROLE_REFUSED"

      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.

    • "LEG_SIDE_NO_PORT"

      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_NATIVE_UNSUPPORTED"

      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_NOT_ON_APPLIANCE"

      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).

    • "NOT_ADDRESSABLE"

      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.

    • "NO_MONITOR_TAKEOVER_ROUTE"

      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.

    • "NO_CUTTABLE_EDGE"

      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.

    • "SWEEP_REFUSED"

      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.

    • "RECORD_REFUSED"

      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.

    • "VSC_REFUSED"

      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.

    • "NO_KEY_SURRENDER"

      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.

    • "CROSS_TRANSPORT_BIND"

      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.

    • "RATE_NOT_DRIVABLE"

      /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.

    • "SPARE_PORT_ABSENT"

      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.

    • "RENDER_REFUSED"

      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.

    • "EXPORT_REFUSED"

      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.

    • "MODE_NOT_LIVE"

      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.

    • "DUPLICATE_MEMBER"

      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.

    • "STAGE_NOT_ON_KIND"

      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.

    • "STAGE_MISSING"

      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.

    • "BOX_PRESENT"

      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.