{"record":{"id":"0f4991285f0ded5e","repo":"BabylonJS/Babylon.js","slug":"error-parsing-node-connections","errorCode":null,"errorMessage":"Error parsing node connections","messagePattern":"Error parsing node connections","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.ts","lineNumber":324,"sourceCode":"                    if (value !== undefined) {\n                        // Update the flow graph block config.\n                        block.config[propertyMapping?.name || key] = {\n                            value: value,\n                        };\n                    }\n                }\n            }\n        }\n    }\n\n    private _parseNodeConnections(context: ISerializedFlowGraphContext) {\n        for (let i = 0; i < this._nodes.length; i++) {\n            // get the corresponding gltf node\n            const gltfNode = this._interactivityGraph.nodes?.[i];\n            if (!gltfNode) {\n                // should never happen but let's still check\n                Logger.Error([\"No node found for interactivity node\", this._nodes[i]]);\n                throw new Error(\"Error parsing node connections\");\n            }\n            const flowGraphBlocks = this._nodes[i];\n            const outputMapper = this._mappings[gltfNode.declaration];\n            // validate\n            if (!outputMapper) {\n                Logger.Error([\"No mapping found for node\", gltfNode]);\n                throw new Error(\"Error parsing node connections\");\n            }\n            // KHR_interactivity spec section 3.2.4 \"Unsupported Operations\":\n            // nodes referring to unsupported operations are demoted to no-ops.\n            // Activations of their input flow sockets are ignored, their output\n            // flow sockets are never activated, and their output value sockets\n            // return constant type-default values. They have no backing\n            // FlowGraph blocks (blocks.length === 0), so there is nothing to\n            // wire for this node — skip all of its connections.\n            if (flowGraphBlocks.blocks.length === 0) {\n                Logger.Warn(`Skipping connections for no-op node #${i} (unsupported operation: ${flowGraphBlocks.fullOperationName})`);\n                continue;","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.ts#L306-L342","documentation":"Thrown in _parseNodeConnections (called from serializeToFlowGraph) when the internal parsed-node list and the glTF nodes array are out of sync, or a glTF node's declaration has no mapping. The first branch is a defensive check that should never happen (parsed node without a backing glTF node); the second mirrors error 706 at connection-wiring time.","triggerScenarios":"Calling serializeToFlowGraph after constructing the parser when `interactivityGraph.nodes[i]` is missing for a parsed node i, or when `this._mappings[gltfNode.declaration]` is undefined because the declaration index is out of range of the parsed mappings.","commonSituations":"Graph mutated after parser construction (nodes removed from the glTF object); assets with out-of-range declaration indices; reusing a parser instance with a modified graph.","solutions":["Do not mutate the interactivity graph object after constructing the parser and before calling serializeToFlowGraph","Ensure every node's `declaration` index is within [0, declarations.length) so mappings resolve","Re-create the parser instance from the final graph data instead of reusing a stale one","Validate the glTF interactivity extension before loading"],"exampleFix":"// before: graph edited between parse and serialize\nconst parser = new InteractivityGraphToFlowGraphParser(graph, gltf);\ngraph.nodes.splice(0, 1); // desync\nparser.serializeToFlowGraph(context);\n// after\nconst parser = new InteractivityGraphToFlowGraphParser(graph, gltf);\nparser.serializeToFlowGraph(context);","handlingStrategy":"try-catch","validationCode":"// Immediately before serializeToFlowGraph:\nconst nodes = graph.nodes ?? [];\nfor (let i = 0; i < nodes.length; i++) {\n  if (!nodes[i] || !(parser.arrays.mappings[nodes[i].declaration])) {\n    throw new Error(`Node ${i} missing or unmapped before serialization`);\n  }\n}","typeGuard":"function graphIntactForSerialization(graph: IKHRInteractivity_Graph, parser: InteractivityGraphToFlowGraphParser): boolean {\n  return (graph.nodes?.length ?? 0) === parser.arrays.nodes.length &&\n    (graph.nodes ?? []).every((n) => parser.arrays.mappings[n.declaration] != null);\n}","tryCatchPattern":"try {\n  const serialized = parser.serializeToFlowGraph(context);\n} catch (e) {\n  if (e.message === 'Error parsing node connections') {\n    console.warn('Graph changed after parsing; rebuilding parser');\n    const fresh = new InteractivityGraphToFlowGraphParser(graph, gltf);\n    return fresh.serializeToFlowGraph(context);\n  }\n  throw e;\n}","preventionTips":["Treat the interactivity graph as immutable between parser construction and serializeToFlowGraph","Build a fresh parser whenever the graph data changes","Construct and serialize in the same function so no intervening code mutates the glTF object","Validate declaration indices before parsing so mappings resolve at connection time"],"tags":["gltf","khr-interactivity","connections","state-desync"],"backgroundTag":"graph-state-desync","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}