BabylonJS/Babylon.js · error · Error
Disconnect failed
Error message
Disconnect failed
What it means
The outBus setter on AbstractSoundSource first disconnects the source from its current output bus via this._disconnect(this._outBus). If that returns false — because the bus no longer lists this source as an upstream node, e.g. the bus was disposed (its onDisposeObservable callback already nulled _outBus elsewhere) or the link was removed out-of-band — the setter throws "Disconnect failed". This indicates the source/bus connection bookkeeping is inconsistent when reassigning outBus.
Source
Thrown at packages/dev/core/src/AudioV2/abstractAudio/abstractSoundSource.ts:94
* The output bus for the sound.
* @see {@link AudioEngineV2.defaultMainBus}
*/
public get outBus(): Nullable<PrimaryAudioBus> {
return this._outBus;
}
public set outBus(outBus: Nullable<PrimaryAudioBus>) {
if (this._outBus === outBus) {
return;
}
if (this._outBus) {
if (this._onOutBusDisposed) {
this._outBus.onDisposeObservable.removeCallback(this._onOutBusDisposed);
this._onOutBusDisposed = null;
}
if (!this._disconnect(this._outBus)) {
throw new Error("Disconnect failed");
}
}
this._outBus = outBus;
if (this._outBus) {
this._onOutBusDisposed = () => {
this._outBus = null;
};
this._outBus.onDisposeObservable.add(this._onOutBusDisposed);
if (!this._connect(this._outBus)) {
throw new Error("Connect failed");
}
}
}
/**
* The spatial audio features.View on GitHub (pinned to 0592b347b8)
Solutions
- Verify the current outBus is still alive before reassigning: check sound.outBus is non-null and the bus is not disposed; if the bus was disposed, _outBus may already be stale — re-check your lifecycle ordering.
- Disconnect explicitly before reassigning: call sound.outBus = null (or bus.disconnect(sound)) in a guarded way, then assign the new bus.
- Ensure only one code path owns bus reassignment; remove duplicate dispose/disconnect callbacks that can race the setter.
- Wrap the assignment in try/catch and, on failure, check whether the old bus was disposed; re-create the source or bus if the graph is inconsistent.
- If you subclass the sound source, make sure _onDisconnect returns true for valid removals.
Example fix
// before
sound.outBus = musicBus; // throws if oldBus was disposed earlier
// after
if (sound.outBus && !sound.outBus.isDisposed) {
sound.outBus = null; // clean detach first
}
sound.outBus = musicBus; Defensive patterns
Strategy: try-catch
Validate before calling
// re-route only if the current bus is alive and actually connected
if (sound.outBus != null && !sound.outBus.isDisposed) {
sound.outBus = null; // clean detach
}
sound.outBus = newBus; Type guard
function hasLiveOutBus(source) {
return source.outBus != null && !source.outBus.isDisposed;
} Try / catch
try {
sound.outBus = newBus;
} catch (e) {
if (e.message === "Disconnect failed") {
// old bus was disposed out-of-band; recreate source or reconnect
sound.outBus = null;
sound.outBus = newBus;
} else {
throw e;
}
} Prevention
- Assign outBus through a single owner; don't mix dispose callbacks with direct reassignment.
- Detach via outBus = null (or bus.disconnect) before routing to a new bus.
- Check bus.isDisposed after any graph rebuild before reusing stale bus references.
- Subscribe to the bus's onDisposeObservable to null out local references instead of relying on them later.
When it happens
Trigger: Assigning sound.outBus = newBus when: the current bus was disposed between connection and assignment (the dispose callback nulls _outBus but the internal sets are inconsistent), the source was already disconnected from the bus via dispose() or manual disconnect(), or a subclass's _onDisconnect override returns false. Note _outBus !== outBus guard means a plain reassignment to the same bus is a no-op.
Common situations: Re-routing a sound after the previous bus was disposed in an audio-graph rebuild; hot-swapping buses during scene teardown while another callback disposed the old bus; assigning outBus from a stale reference kept across engine resets.
Related errors
- Disconnect failed
- The value passed to [Scene.audioListenerPositionProvider] mu
- The value passed to [Scene.audioListenerRotationProvider] mu
- No volume subnode
- Connect failed
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/5194656a6e2ec974.
Report an issue: GitHub.