{"record":{"id":"45ccb99bab085edf","repo":"phaserjs/phaser","slug":"node","errorCode":null,"errorMessage":"node ","messagePattern":"node ","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/webgl/renderNodes/RenderNodeManager.js","lineNumber":310,"sourceCode":"         * @default null\n         */\n        this.currentDebugNode = null;\n    },\n\n    /**\n     * Add a node to the manager.\n     *\n     * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#addNode\n     * @since 4.0.0\n     * @param {string} name - The name of the node.\n     * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNode} node - The node to add.\n     * @throws {Error} Will throw an error if the node already exists.\n     */\n    addNode: function (name, node)\n    {\n        if (this._nodes[name])\n        {\n            throw new Error('node ' + name + ' already exists.');\n        }\n        this._nodes[name] = node;\n\n        // If a node is somehow added during a debug render pass,\n        // ensure that it is also set to debug.\n        if (this.debug)\n        {\n            node.setDebug(true);\n        }\n    },\n\n    /**\n     * Add a constructor for a node to the manager.\n     * This will allow the node to be constructed when `getNode` is called.\n     *\n     * @method Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager#addNodeConstructor\n     * @since 4.0.0\n     * @param {string} name - The name of the node.","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/phaserjs/phaser/blob/41be1e462bc600064e498cba370bfa8c5c055a22/src/renderer/webgl/renderNodes/RenderNodeManager.js#L292-L328","documentation":"Thrown by RenderNodeManager.addNode when a node is registered under a name that already exists in this._nodes. Names are unique keys into the render-graph registry because getNode looks nodes up by name and the system assumes one instance per name.","triggerScenarios":"Calling manager.addNode(name, node) twice with the same name string; adding a node whose name collides with a built-in node (e.g. 'BatchHandlerQuad'); a plugin or scene adding a node that another plugin already registered.","commonSituations":"Two plugins registering custom render nodes with the same name; hot-reloading a scene/plugin that re-adds its nodes without tearing down the old ones; reusing a generic name like 'batch' across modules.","solutions":["Namespace your node names (e.g. 'MyPlugin.BatchHandler') to avoid collisions with built-ins and other plugins.","Before adding, check manager._nodes[name] or guard with a removeNode call if re-registering is expected.","On teardown/hot-reload, remove previously added nodes before re-adding them.","Use addNodeConstructor + getNode (lazy construction) instead of eagerly adding duplicate instances."],"exampleFix":"// before\nmanager.addNode('Batch', nodeA);\nmanager.addNode('Batch', nodeB); // throws\n\n// after\nif (!manager._nodes['Batch']) {\n  manager.addNode('Batch', nodeA);\n} else {\n  manager.removeNode('Batch');\n  manager.addNode('Batch', nodeB);\n}","handlingStrategy":"validation","validationCode":"if (manager._nodes[name]) { /* skip or remove+re-add */ } else { manager.addNode(name, node); }","typeGuard":"function isNodeRegistered(manager, name) { return Boolean(manager._nodes && manager._nodes[name]); }","tryCatchPattern":"try { manager.addNode(name, node); } catch (e) { if (/already exists/.test(e.message)) { manager.removeNode(name); manager.addNode(name, node); } else throw e; }","preventionTips":["Namespace node names by plugin/owner.","Register once at bootstrap, not per scene.","Remove nodes on plugin destroy."],"tags":["renderer","webgl","render-node","registry","phaser4"],"backgroundTag":null,"analyzedSha":"41be1e462bc600064e498cba370bfa8c5c055a22","analyzedAt":"2026-08-13T04:23:39.729Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}