BabylonJS/Babylon.js · error · Error

No volume subnode

Error message

No volume subnode

What it means

The volume setter on AbstractAudioOutNode (implemented by sounds, sound sources, and buses in Babylon.js Audio V2) assumes a volume audio subnode was created when the node was initialized, as the in-code comment states. _GetVolumeAudioSubNode(this._subGraph) returned null, so assigning node.volume throws "No volume subnode". This means the node's sub-graph was never initialized or has already been disposed.

Source

Thrown at packages/dev/core/src/AudioV2/abstractAudio/abstractAudioOutNode.ts:43

    /**
     * The audio analyzer features.
     */
    public get analyzer(): AbstractAudioAnalyzer {
        return this._analyzer ?? (this._analyzer = new _AudioAnalyzer(this._subGraph));
    }

    /**
     * The audio output volume.
     */
    public get volume(): number {
        return _GetVolumeAudioProperty(this._subGraph, "volume");
    }

    public set volume(value: number) {
        // The volume subnode is created on initialization and should always exist.
        const node = _GetVolumeAudioSubNode(this._subGraph);
        if (!node) {
            throw new Error("No volume subnode");
        }

        node.volume = value;
    }

    /**
     * Releases associated resources.
     */
    public override dispose(): void {
        super.dispose();

        this._analyzer?.dispose();
        this._analyzer = null;

        this._subGraph.dispose();
    }

    /**

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Wait for node readiness before setting volume — e.g. use the async creation API (await SoundV2.CreateAsync / engine.createSoundAsync) so the subgraph and its volume subnode exist.
  2. Check that the node has not been disposed; do not touch volume after calling dispose() or after the engine is released.
  3. Verify the Web Audio context/engine is still running; a suspended/closed engine can prevent subnode creation.
  4. If you cannot guarantee timing, wrap the assignment in try/catch and treat "No volume subnode" as 'node not ready or disposed'.

Example fix

// before
const sound = await engine.createSoundAsync(url);
sound.dispose();
sound.volume = 0.5; // throws

// after
const sound = await engine.createSoundAsync(url);
if (!sound.isDisposed) {
    sound.volume = 0.5;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// set volume only when the node is ready and not disposed
if (!sound.isDisposed && engine.state === "Started") {
    sound.volume = 0.5;
}

Type guard

function canSetVolume(node) {
    return node != null && !node.isDisposed && typeof node.volume === "number";
}

Try / catch

try {
    sound.volume = 0.5;
} catch (e) {
    if (e.message === "No volume subnode") {
        // node not initialized or already disposed; retry after ready or skip
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Setting `node.volume = x` on an audio node whose _subGraph has no volume subnode — typically after calling dispose() on the node, before async initialization of the subgraph completed, or if the subgraph failed to create its subnodes (e.g. audio engine/context not ready).

Common situations: Setting volume after sound.dispose() in a UI callback firing late; setting volume immediately after construction before the sound's internal async creation promise resolves; engine shutdown or context loss tearing down subnodes while app code still holds the node reference.

Related errors


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