BabylonJS/Babylon.js · error · Error
Disconnect failed
Error message
Disconnect failed
What it means
AudioBus.outBus setter throws "Disconnect failed" when, before installing a new out bus, it tries to _disconnect(this._outBus) from the previous bus and the disconnect returns false. This only happens when the setter already had an out bus attached. It indicates the previous bus's underlying audio node could not be detached, usually because the node graph is not ready or the previous bus was already disposed.
Source
Thrown at packages/dev/core/src/AudioV2/abstractAudio/audioBus.ts:63
}
/**
* The output bus of the audio bus. Defaults to the audio engine's default main bus.
*/
public get outBus(): Nullable<PrimaryAudioBus> {
return this._outBus;
}
public set outBus(outBus: Nullable<PrimaryAudioBus>) {
if (this._outBus === outBus) {
return;
}
if (this._outBus) {
this._outBus.onDisposeObservable.removeCallback(this._onOutBusDisposed);
if (!this._disconnect(this._outBus)) {
throw new Error("Disconnect failed");
}
}
this._outBus = outBus;
if (this._outBus) {
this._outBus.onDisposeObservable.add(this._onOutBusDisposed);
if (!this._connect(this._outBus)) {
throw new Error("Connect failed");
}
}
}
/**
* The spatial audio features.
*/
public get spatial(): AbstractSpatialAudio {View on GitHub (pinned to 0592b347b8)
Solutions
- Set outBus = null before disposing the old bus so the setter's disconnect path is not taken on a dead bus.
- Perform reassignments while the audio engine is running/ready, not during teardown.
- Check the previous bus is still alive (held in engine.buses) before reassigning.
- Catch the error and clear _outBus state by disposing and recreating the bus.
Example fix
// before busA.dispose(); busA.outBus = busB; // disconnect from disposed busA path fails // after busA.outBus = null; // cleanly detach first busA.dispose(); // or reassign while both buses are alive and engine is running busA.outBus = busB;
Defensive patterns
Strategy: validation
Validate before calling
function canReassignOutBus(oldBus, newBus) {
return (!oldBus || (!oldBus.isDisposed && audioEngine.state === 'started')) && !!newBus && !newBus.isDisposed;
}
if (canReassignOutBus(busA, busB)) busA.outBus = busB; else busA.outBus = null; Type guard
function isConnectableBus(x) {
return x === null || (x instanceof AudioBus && !x.isDisposed);
} Try / catch
try {
busA.outBus = busB;
} catch (e) {
if (e.message === 'Disconnect failed') {
busA.dispose(); // recover by rebuilding routing
} else throw e;
} Prevention
- Set outBus = null before disposing a bus that is another node's outBus.
- Do runtime rerouting only while the engine is running; defer during scene teardown.
- Track bus ownership so a disposed bus is never passed to a setter.
- Guard reassignments behind engine-ready flags.
When it happens
Trigger: Reassigning audioBus.outBus from busA to busB while busA was disposed before the reassignment, or while the audio engine was suspended/not yet started so the underlying disconnect fails.
Common situations: Switching a bus's output routing at runtime (e.g. moving 'SFX' bus from main output to a recorder bus) during a scene teardown where the old bus was disposed; hot-reload or scene restart code that disposes buses but reassigns outBus afterwards.
Related errors
- No volume subnode
- Connect failed
- Connect failed
- The value passed to [Scene.audioListenerPositionProvider] mu
- The value passed to [Scene.audioListenerRotationProvider] mu
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/5f4508991b502fe1.
Report an issue: GitHub.