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

  1. Set outBus = null before disposing the old bus so the setter's disconnect path is not taken on a dead bus.
  2. Perform reassignments while the audio engine is running/ready, not during teardown.
  3. Check the previous bus is still alive (held in engine.buses) before reassigning.
  4. 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

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


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/5f4508991b502fe1. Report an issue: GitHub.