REST reference

Refusal and undo-label codes

Nothing below the surface ever emits display prose. A refusal, a warning or an undo-entry label travels as a stable code plus a small record of named parameters, and the client renders it in the operator's own locale. 106 codes, generated from the registry that also gates the server's own build. All families

server refusals (shipped wire codes — do not rename)

CodeParametersWhat it means
no-state-dir—No `--state-dir`/`OPENMIXER_STATE_DIR`, so nothing the operator sets can persist.
takeover-unsupported—This server cannot take the device graph over from whatever owns it.
no-stagebox-registry—No persisted stagebox registry, so a rename has nothing to write to.
invalid-message—The request did not parse against the wire schema.
sip-disarmed—Solo-in-place is locked; it must be unlocked in Setup first.
sip-needs-confirm—Solo-in-place needs the explicit second step (it mutes the house mix in place).

stagebox bulk-assignment refusals (core `StageboxAssignError`)

CodeParametersWhat it means
stagebox.assign.unknown-device—See StageboxAssignRefusalParams.
stagebox.assign.no-such-side—See StageboxAssignRefusalParams.
stagebox.assign.clear-outputs-unsupported—See StageboxAssignRefusalParams.
stagebox.assign.bad-start-channel—See StageboxAssignRefusalParams.
stagebox.assign.exceeds-box-width—See StageboxAssignRefusalParams.
stagebox.assign.exceeds-audio-fabric—See StageboxAssignRefusalParams.

insert latency-budget findings (core `judgeChainLatency`)

CodeParametersWhat it means
insert.latency.exceeds-budget—See LatencyBudgetParams.
insert.latency.may-exceed-budget—See LatencyBudgetParams.
insert.latency.unknown-at-rate—See LatencyBudgetParams.
insert.latency.within-budget—See LatencyBudgetParams.

engine real-time headroom

CodeParametersWhat it means
rt.budgetpctThe engine's measured share of its real-time budget.

plugin analysis (issue #342)

CodeParametersWhat it means
measurement.engine-livepctThe engine is processing audio, so a CPU-heavy plugin sweep is refused.
measurement.already-running—A sweep is already in progress; a second one would fight it for the CPU.
measurement.no-rates—Neither a live rate nor a supported-rate list is known, so nothing can be measured.
measurement.nothing-local—Nothing has been measured on this machine, so there is nothing to discard.

the plugin host's instance table (audio-engine `ModHostClient`)

CodeParametersWhat it means
plugins.instances-exhaustedmax, leakedEvery mod-host instance id is spoken for, so no further plugin can be racked.

multitrack record (2026-07-16-recording-vsc.md §2.3)

CodeParametersWhat it means
record.already-running—A take is already running; a second one would give a channel two rings and neither would hold the whole show.
record.nothing-armed—No channel would be captured — everything is opted out, or nothing is patched. Starting anyway produces a folder nobody can explain the next morning.
record.no-spaceneedBytes, freeBytesThe disk cannot hold the take's first minutes, so starting would be a promise it cannot keep and the show would truncate at the worst moment.
record.no-engine—There is no audio engine to record from.
record.rate-unknown—The graph has not resolved a sample rate, so there is nothing honest to stamp the take with. A take carries the rate it was captured at (§5) and the NODE is the only thing that knows what that is; a file stamped with a default is one the desk will later refuse to play and cannot explain (2026-09-01).

the offline HRP render (2026-07-16-recording-vsc.md §0.5)

CodeParametersWhat it means
render.no-engine—This build carries no offline render engine, so the console cannot render a take.
render.no-tracks—Not one track of the take could be opened as a renderable file.
render.no-spaceneedBytes, freeBytesA render writes a second copy of every selected track, and the disk cannot hold it. Refused BEFORE the first sample rather than halfway through a folder of half-files.
render.already-running—One render at a time: two at once would only halve each other's speed.

the MAIN print export (2026-07-16-recording-vsc.md §0.6)

CodeParametersWhat it means
export.no-engine—The console has no take library, so nothing can be exported.
export.no-main—The take carries no MAIN capture, and the print IS the main capture — there is nothing lesser to offer in its place.
export.empty—The MAIN capture holds no frames: an armed track whose source never made a sound.
export.unreadable—The MAIN capture cannot be read as a float WAV, so no print can be made from it.
export.no-spaceneedBytes, freeBytesThe print does not fit on the disk. Refused BEFORE the first sample, like a render's.
export.already-running—One export at a time, for `render.already-running`'s reason.
render.recording—A take is being CAPTURED. §0.5 puts rendering on a console that is idle after the show, and a capture is the one thing here that cannot be done again.
render.playback—A virtual soundcheck is replaying, which is the desk in use.
record.vsc-active—A take is loaded for a virtual soundcheck, and record XOR playback holds on one graph (§3.5): capturing while a soundcheck replays would write yesterday's take back to disk under a new name, with nothing to tell the two apart.

virtual soundcheck (2026-07-16-recording-vsc.md §3)

CodeParametersWhat it means
vsc.no-take—No take is loaded, so there is nothing for a channel to listen to.
vsc.no-track—The take carries no track for this channel, so it stays on its live input — a soundcheck never replays silence over a microphone that is working (§3.2).
vsc.rate-mismatchtakeRate, graphRateThe take was captured at one rate and the graph runs at another. There is no resampler on the playback path by design (§5), so it would play at the wrong pitch and the wrong length: match the clock or re-record.
vsc.recording—A take is being RECORDED, and record XOR playback holds on one graph (§3.5).
vsc.no-such-take—The take id names nothing in the take library.
vsc.take-unplayable—The take is there and its audio is not playable — a missing, truncated or re-encoded track file. A soundcheck missing one channel is worse than one that did not start, because nothing about it looks wrong.
vsc.no-engine—There is no audio engine to play a take through.
vsc.not-engaged—Play means hear it (§3.4): the write would run the transport with no channel listening to the take, so it is refused. Engage in the same write, or check the take can serve these channels.

discovery blindness: the headline

CodeParametersWhat it means
discovery.blind.linkprotocol, scopeA protocol's probe could not scan one named link.
discovery.blind.globalprotocolA protocol's probe could not scan at all.

discovery blindness: why (REAC raw-socket prober)

CodeParametersWhat it means
discovery.reac.nic-enumeration-failederrorThe host's NIC list could not be read, so no link was looked at.
discovery.reac.passive-listen-failederrorThe passive listen threw on this link.
discovery.reac.active-probe-failederrorThe active probe threw on this link.
discovery.reac.link-busyrxDeltaThe link carries traffic, so it was deliberately NOT active-probed.
discovery.reac.active-probe-no-reason—The active probe declined to run and gave no reason.

discovery blindness: why (reac-pw property prober)

CodeParametersWhat it means
discovery.reac.registry-unloaded—The native PipeWire registry is not loaded, so reac-pw's discovery cannot be read.
discovery.reac.not-publishing—No reac-playback node is publishing discovery on this host.
discovery.reac.predates-discovery—This reac-pw predates the discovery properties.
discovery.reac.unknown-statestatereac-pw reports a discovery state this build does not understand.
discovery.reac.unparseable—reac-pw published discovery data that did not parse.
discovery.reac.stalesecondsEvery published sighting has aged out — the publisher appears wedged.
discovery.reac.not-listening-herescopesreac-pw is watching other NICs, so this one went unscanned.

clock cross-checks (Setup → Clock, and the warnings badge)

CodeParametersWhat it means
clock.no-owner.title—openmixer is following and nothing on the segment was seen owning the pace.
clock.no-owner.detail—No parameters — the sentence is fixed text.
clock.two-owners.title—openmixer owns the pace and so does something else — the classic click/dropout cause.
clock.two-owners.detailownerThe code → message bridge: THE registry of every operator-facing message core and the server may put on the wire, each mapped to the exact named fields its localised sentence interpolates. The rule (i18n design of record, §"server/core send CODES"): nothing below the UI ever emits display prose. A refusal, a warning, an undo label — each travels as a stable kebab/dotted CODE plus a small record of structured parameters, and the client renders it in the operator's own locale. Untranslatable payloads (a device id, a NIC name, a plugin product name, a count) ride as PARAMETERS; they are never baked into a sentence server-side, because a baked sentence cannot be translated and a re-ordered one cannot be un-baked. ## Why a registry and not just `string` A bare `{ code: string; params: Record<string, unknown> }` moves the failure to runtime: the sentence renders with `{scope}` still in it because the emitter sent `nic`. {@link MessageParams} pins each code to its parameter shape, so ```ts codedMessage('rt.budget', { pct: 92 }); // ok codedMessage('rt.budget', { percent: 92 }); // build error — wrong field codedMessage('rt.budget', {}); // build error — missing field codedMessage('not-a-real-code', {}); // build error — unknown code ``` and {@link AnyCodedMessage} is the discriminated union over every entry, so a consumer that switches on `code` gets that code's parameters typed with no assertion at the branch. ## Adding a message 1. Add the code + its parameter type to {@link MessageParams}. 2. Add it to {@link MESSAGE_CODES} (the build fails until you do — see `_NoUnlistedCode`). 3. Add the sentence to EVERY locale catalog (`web-ui/i18n/locales/<code>/messages.json`); the catalog-parity test fails until you do. / import type { InsertLatencyCode, LatencyBudgetParams } from './insert-latency-budget.js'; import type { StageboxAssignRefusal, StageboxAssignRefusalParams } from './stagebox.js'; /** What a localised sentence may interpolate: wire-serialisable scalars only. */ export type MessageParamValue = string | number; /** The parameter record shape every {@link MessageParams} entry conforms to. */ export type MessageParamRecord = Readonly<Record<string, MessageParamValue>>; /** The parameter type of a code whose sentence interpolates nothing. */ export type NoMessageParams = Readonly<Record<string, never>>; // --------------------------------------------------------------------------- // Parameter shapes // // Declared as TYPE ALIASES, never interfaces: an anonymous/aliased object type carries an // implicit index signature, so it is assignable to `MessageParamRecord` at the translator // boundary. An `interface` would not be, and every call site would need a cast. // --------------------------------------------------------------------------- /** How much of the real-time budget the engine is spending. */ export type RtBudgetParams = { readonly pct: number }; /** How busy the engine was when a plugin analysis was refused. */ export type MeasurementBusyParams = { readonly pct: number }; /** Why the plugin host has no instance slot left: how many ids mod-host has (`max`, its own declared `0 ~ N` range) and how many of them are LEAKED — bypassed, un-racked, and still holding their id because mod-host's `remove` command segfaults this build, so an un-rack never returns a slot. Both numbers, because "the plugin host is full" leaves an operator guessing while "9991 slots, 9991 of them leaked" says the fix is to restart the host. / export type PluginInstancesParams = { readonly max: number; readonly leaked: number }; /** What the record gate found short: the bytes it wants before it will start, and the bytes the disk actually has. Both, because "the disk is full" leaves an operator guessing what to delete while "it needs 14 GB and has 3" tells them exactly how much. */ export type RecordSpaceParams = { readonly needBytes: number; readonly freeBytes: number }; /** The two rates a virtual soundcheck could not reconcile — the take's and the graph's. Both numbers, because "the rates do not match" leaves an operator guessing which one to move. */ export type VscRateParams = { readonly takeRate: number; readonly graphRate: number }; /** What a render needs and what the disk has. Both numbers, for the same reason the recorder's are both numbers: "not enough space" leaves an operator guessing what to free. */ export type RenderSpaceParams = { readonly needBytes: number; readonly freeBytes: number }; /** A discovery protocol that could not scan a specific link. */ export type BlindLinkParams = { readonly protocol: string; readonly scope: string }; /** A discovery protocol that could not scan at all (no link scope). */ export type BlindGlobalParams = { readonly protocol: string }; /** A probe that failed with a host/system error, named for the operator. */ export type ProbeErrorParams = { readonly error: string }; /** A link too busy to active-probe, with what the listen window actually saw. */ export type BusyLinkParams = { readonly rxDelta: number }; /** A reac-pw publishing a discovery state this build has no meaning for. */ export type UnknownProbeStateParams = { readonly state: string }; /** A reac-pw whose published sightings have all aged out. */ export type StaleProbeParams = { readonly seconds: number }; /** The NIC scopes reac-pw IS watching, for a NIC it is not. */ export type OtherScopesParams = { readonly scopes: string }; /** A device absent from a restored show, with its dependency clauses already joined. */ export type MissingHardwareParams = { readonly name: string; readonly clauses: string }; /** A count of restored patches/routes that depend on an absent device. */ export type DependentCountParams = { readonly n: number }; /** The NIC an absent box is configured on. */ export type ConfiguredIfaceParams = { readonly iface: string }; /** A stored value that disagrees with what the hardware reports. Both halves are parameters because the sentence around them is the locale's; `observed` is the one that wins. / export type ContradictionParams = { readonly declared: string; readonly observed: string }; /** The same, for a fact counted rather than named (a width, a channel count). */ export type ContradictionCountParams = { readonly declared: number; readonly observed: number }; /** A hardware-backed entity whose device is not on the rig: what it is, and which one. */ export type AbsentDeviceParams = { readonly kind: string; readonly id: string }; /** The device observed owning the clock pace alongside openmixer.
clock.unqualified-master.title—openmixer owns the pace off a reference that does not qualify for it.
clock.synthetic-driver.titlelabelA software timer is driving the graph: audio runs, its timing means nothing.
clock.synthetic-driver.detail—No parameters — the sentence is fixed text.

xrun cross-checks (issue #657: warn, with numbers, never block)

CodeParametersWhat it means
xrun.growing.titlerateXruns are landing now (a delta since the previous observation, never the running total).
xrun.growing.detail.raisetotal, quantum, quantumMs, sampleRate, recommendedRoom to raise the quantum; no node's request explains the current one.
xrun.growing.detail.raise-holdertotal, quantum, quantumMs, sampleRate, recommended, label, holderMsRoom to raise the quantum, AND a node's request explains the current one.
xrun.growing.detail.relaxtotal, quantum, quantumMs, sampleRate, label, holderMsNo room left to raise (at the ceiling); a node's request explains the current quantum.
xrun.growing.detail.unknowntotal, quantum, quantumMs, sampleRateNo room left to raise, and no node's request explains the current quantum either.

absent hardware after a session restore

CodeParametersWhat it means
hardware.missing.summaryname, clausesThe whole "what depends on this absent device" line, built from the clauses below.
hardware.missing.clause-separator—What joins two clauses — keyed so a locale can punctuate its own way.
hardware.missing.input-patchesnRestored channel input patches feeding from the absent device.
hardware.missing.output-routesnRestored bus output routes feeding to the absent device.
hardware.missing.no-patches—The device is absent but nothing in the show is patched to it.
hardware.missing.configured-onifaceThe rig's own configuration expects this box on a named NIC.
hardware.missing.not-connected—The bridge sees the box's node but the box has not established.
hardware.missing.bridge-down—The REAC bridge itself is down, so nothing could establish.
hardware.missing.surface—The absent device is a control surface.

a stored value contradicted by the hardware itself

CodeParametersWhat it means
hardware.contradiction.modeldeclared, observedThe configured box model is not the model the box reports. The box wins.
hardware.contradiction.widthdeclared, observedThe configured channel width is not the width the box reports. The box wins.
hardware.contradiction.channelsdeclared, observedThe configured preamp count is not the count the box reports. The box wins.

routing loops (howl-round topology, issue #378)

CodeParametersWhat it means
feedback.loop.no-cuttable-edge—The standing routing loop runs entirely through console structure — no operator patch lies on it, so there is nothing a break may cut without dismantling the desk.

undo / redo entry labels

CodeParametersWhat it means
undo.label.routefrom, toA route toggled between two scopes.
undo.label.bpm—The desk tempo.
undo.label.stripOrder—The desk's strip order — the `/channel` roster reordered (console-wide, no strip scope).
undo.label.gaterefA strip's gate.
undo.label.delayrefA strip's delay.
undo.label.reverbrefA strip's reverb.
undo.label.eqrefA channel's EQ.
undo.label.pastecountA clipboard paste onto one or more channels (#57) — `count` is how many it landed on.
undo.label.sendfrom, toA send's level or tap — `from` is the source strip, `to` the destination bus.

Undo — per-parameter labels

CodeParametersWhat it means
undo.label.set.faderrefAn undo entry naming one console scope.
undo.label.set.gainrefAn undo entry naming one console scope.
undo.label.set.panrefAn undo entry naming one console scope.
undo.label.set.trimrefAn undo entry naming one console scope.
undo.label.set.phantomrefAn undo entry naming one console scope.
undo.label.set.polarityrefAn undo entry naming one console scope.
undo.label.set.alignrefAn undo entry naming one console scope.
undo.label.set.namerefAn undo entry naming one console scope.
undo.label.set.colourrefAn undo entry naming one console scope.
undo.label.set.instrumentrefAn undo entry naming one console scope.

openmixer

A software mixing console for Linux. The desk is the software; the browser is the surface.

Pages

Licence

OpenMixer is free software under the GPL-3.0-or-later. Every package in the workspace carries the same licence.

Roland, Midas, Behringer, RME and the product names used here belong to their respective owners. OpenMixer is an independent project and is not affiliated with any of them.