{"record":{"id":"25880e0307a1e95a","repo":"phaserjs/phaser","slug":"batchhandler-must-have-a-name","errorCode":null,"errorMessage":"BatchHandler must have a name","messagePattern":"BatchHandler must have a name","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/webgl/renderNodes/BatchHandler.js","lineNumber":47,"sourceCode":" * @extends Phaser.Renderer.WebGL.RenderNodes.RenderNode\n * @param {Phaser.Renderer.WebGL.RenderNodes.RenderNodeManager} manager - The manager that owns this RenderNode.\n * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} defaultConfig - The default configuration object for this RenderNode. This is used to ensure all required properties are present, so it must be complete.\n * @param {Phaser.Types.Renderer.WebGL.RenderNodes.BatchHandlerConfig} [config] - The configuration object for this RenderNode.\n */\nvar BatchHandler = new Class({\n    Extends: RenderNode,\n\n    initialize: function BatchHandler (manager, defaultConfig, config)\n    {\n        var renderer = manager.renderer;\n        var gl = renderer.gl;\n\n        config = this._copyAndCompleteConfig(manager, config || {}, defaultConfig);\n\n        var name = config.name;\n        if (!name)\n        {\n            throw new Error('BatchHandler must have a name');\n        }\n\n        RenderNode.call(this, name, manager);\n\n        /**\n         * The number of instances per batch, used to determine the size of the\n         * vertex buffer, and the number of instances to render.\n         *\n         * This is usually limited by the maximum number of vertices that can be\n         * distinguished with a 16-bit UNSIGNED_INT index buffer,\n         * which is 65536. This is set in the game render config as `batchSize`.\n         *\n         * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#instancesPerBatch\n         * @type {number}\n         * @since 4.0.0\n         */\n        this.instancesPerBatch = -1;\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/phaserjs/phaser/blob/41be1e462bc600064e498cba370bfa8c5c055a22/src/renderer/webgl/renderNodes/BatchHandler.js#L29-L65","documentation":"Thrown by the BatchHandler render node constructor when its config has no 'name' property after _copyAndCompleteConfig runs. Every RenderNode (the base class) requires a name to register with the RenderNodeManager, so a batch handler without one cannot be created. The name is what getNode/addNode use to look the node up later, so an empty/falsy name is a hard stop rather than a defaultable value.","triggerScenarios":"Constructing a BatchHandler (or subclass like BatchHandlerQuad, BatchHandlerTri) directly or via RenderNodeManager.addNode/getNode with a config object where 'name' is undefined, null, or empty string. Happens when a custom BatchHandler subclass overrides defaultConfig but omits the name key, or when a node constructor is registered and instantiated without a config.name being supplied by the caller.","commonSituations":"Authoring a custom render node in Phaser 4's new render-graph system and forgetting the 'name' field in the node config; copy-pasting a BatchHandler subclass and stripping the name; migrating from Phaser 3 where names were implicit.","solutions":["Provide a 'name' string in the config passed to the BatchHandler constructor (or in the subclass defaultConfig), e.g. config.name = 'MyBatchHandler'.","If registering via RenderNodeManager.addNodeConstructor/getNode, ensure the registration name flows into config.name.","Audit any BatchHandler subclass's defaultConfig to confirm it sets a name.","If you do not need a custom node, use one of the built-in BatchHandler subclasses which already define names."],"exampleFix":"// before\nmanager.addNodeConstructor('MyBatch', function (manager) {\n  return new BatchHandler(manager, {}, {}); // missing name\n});\n\n// after\nmanager.addNodeConstructor('MyBatch', function (manager) {\n  return new BatchHandler(manager, {}, { name: 'MyBatch' });\n});","handlingStrategy":"validation","validationCode":"function ensureBatchHandlerName(config) {\n  if (!config || typeof config.name !== 'string' || config.name.length === 0) {\n    throw new TypeError('BatchHandler config.name must be a non-empty string');\n  }\n  return config;\n}","typeGuard":"function isBatchHandlerConfig(c) {\n  return c != null && typeof c === 'object' && typeof c.name === 'string' && c.name.length > 0;\n}","tryCatchPattern":"try {\n  node = new BatchHandler(manager, defaultCfg, cfg);\n} catch (e) {\n  if (/must have a name/.test(e.message)) { /* fix config.name and retry or report */ }\n  else throw e;\n}","preventionTips":["Always set config.name when constructing render nodes.","Centralize node construction behind a factory that asserts the name.","Keep a single source of truth for node names as constants."],"tags":["renderer","webgl","render-node","config","phaser4"],"backgroundTag":null,"analyzedSha":"41be1e462bc600064e498cba370bfa8c5c055a22","analyzedAt":"2026-08-13T04:23:39.729Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}