BabylonJS/Babylon.js · error · Error

Error parsing nodes

Error message

Error parsing nodes

What it means

Thrown in _parseNodes when an interactivity node is missing a numeric `declaration` index. Every node must reference an entry in the graph's `declarations` array by index; a missing or non-numeric declaration makes the node un-mappable to FlowGraph blocks.

Source

Thrown at packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.ts:239

                        type: type.flowGraphType,
                        eventData: true,
                        value,
                    };
                });
            }
            this._events.push(converted);
        }
    }

    private _parseNodes() {
        if (!this._interactivityGraph.nodes) {
            return;
        }
        for (const node of this._interactivityGraph.nodes) {
            // some validation
            if (typeof node.declaration !== "number") {
                Logger.Error(["No declaration found for node", node]);
                throw new Error("Error parsing nodes");
            }
            const mapping = this._mappings[node.declaration];
            if (!mapping) {
                Logger.Error(["No mapping found for node", node]);
                throw new Error("Error parsing nodes");
            }
            if (mapping.flowGraphMapping.validation) {
                const validationResult = mapping.flowGraphMapping.validation(node, this._interactivityGraph, this._gltf);
                if (!validationResult.valid) {
                    throw new Error(`Error validating interactivity node ${this._interactivityGraph.declarations?.[node.declaration].op} - ${validationResult.error}`);
                }
            }
            const blocks: ISerializedFlowGraphBlock[] = [];
            // create block(s) for this node using the mapping
            for (const blockType of mapping.flowGraphMapping.blocks) {
                const block = this._getEmptyBlock(blockType, mapping.fullOperationName);
                this._parseNodeConfiguration(node, block, mapping.flowGraphMapping, blockType);
                blocks.push(block);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Add a valid numeric `declaration` index to each node, referencing the graph's `declarations` array
  2. If the node was meant to declare an op inline, move the op into `declarations` and reference it by index
  3. Validate the asset against the KHR_interactivity JSON schema before loading
  4. Re-export with a current exporter

Example fix

// before
{ "configuration": {} }
// after
{ "declaration": 0, "configuration": {} }
Defensive patterns

Strategy: validation

Validate before calling

for (const node of graph.nodes ?? []) {
  if (typeof node.declaration !== 'number') throw new Error(`Node missing numeric declaration: ${JSON.stringify(node).slice(0, 80)}`);
}

Type guard

function nodeHasDeclaration(node: IKHRInteractivity_Node): node is IKHRInteractivity_Node & { declaration: number } {
  return typeof (node as any).declaration === 'number';
}

Try / catch

try {
  const parser = new InteractivityGraphToFlowGraphParser(graph, gltf);
} catch (e) {
  if (e.message === 'Error parsing nodes') {
    console.warn('Interactivity node missing declaration; loading without interactivity');
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: A node in `interactivity.nodes` has no `declaration` property, a null declaration, or a non-number (e.g. a string op name instead of an index) — checked via `typeof node.declaration !== "number"`.

Common situations: Hand-written or hand-edited glTF where the author put the op name directly on the node; older/incorrect exporter output; JSON schema drift between KHR_interactivity draft versions.

Related errors


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