{"record":{"id":"1586ee8f6b71ed63","repo":"mrdoob/three.js","slug":"three-batchedmesh-invalid-geometryid-geometryid","errorCode":null,"errorMessage":"THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.","messagePattern":"THREE\\.BatchedMesh: Invalid geometryId (.+?)\\. Geometry is either out of range or has been deleted\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/objects/BatchedMesh.js","lineNumber":474,"sourceCode":"\t\tif ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {\n\n\t\t\tthrow new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Validates the geometry defined by the given ID.\n\t *\n\t * @param {number} geometryId - The geometry to validate.\n\t */\n\tvalidateGeometryId( geometryId ) {\n\n\t\tconst geometryInfoList = this._geometryInfo;\n\t\tif ( geometryId < 0 || geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {\n\n\t\t\tthrow new Error( `THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.` );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Takes a sort a function that is run before render. The function takes a list of instances to\n\t * sort and a camera. The objects in the list include a \"z\" field to perform a depth-ordered sort with.\n\t *\n\t * @param {Function} func - The custom sort function.\n\t * @return {BatchedMesh} A reference to this batched mesh.\n\t */\n\tsetCustomSort( func ) {\n\n\t\tthis.customSort = func;\n\t\treturn this;\n\n\t}","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/src/objects/BatchedMesh.js#L456-L492","documentation":"Thrown by BatchedMesh.validateGeometryId() when the geometryId is negative, greater than or equal to the geometry info list length, or refers to a deleted (inactive) geometry. APIs like addInstance(geometryId) validate the geometry id first.","triggerScenarios":"Using a geometryId returned before deleteGeometry() was called; passing a geometry index that was never added; referencing a geometry id across a repack/optimize that invalidated it; off-by-one indexing.","commonSituations":"Caching geometry ids across geometry deletion/re-addition; assuming ids are contiguous after deletion; passing the index into a user array instead of the BatchedMesh-returned geometryId.","solutions":["Use only the id returned by addGeometry(); do not assume ids are contiguous after deletions.","Invalidate cached geometry ids when the corresponding geometry is deleted.","Bound-check the id against the geometry count and track active ids in your own map."],"exampleFix":"// before\nbatch.deleteGeometry( geometryId );\nbatch.addInstance( geometryId ); // geometryId now invalid\n\n// after\nbatch.deleteGeometry( geometryId );\n// remove geometryId from your lookup; re-add geometry if still needed","handlingStrategy":"validation","validationCode":"function isValidGeometryId( batch, id ) {\n  const list = batch._geometryInfo;\n  return id >= 0 && id < list.length && list[ id ].active === true;\n}\n\nif ( ! isValidGeometryId( batch, id ) ) throw new RangeError( `Invalid geometryId ${ id }` );","typeGuard":"const isActiveGeometry = ( batch, id ) => isValidGeometryId( batch, id );","tryCatchPattern":"try {\n  batch.addInstance( geometryId );\n} catch ( e ) {\n  if ( /Invalid geometryId/.test( e.message ) ) {\n    // geometry was deleted; re-add or skip\n  } else throw e;\n}","preventionTips":["Use only ids returned by addGeometry().","Do not assume geometry ids stay contiguous after deletions.","Clear cached geometry ids when the geometry is deleted."],"tags":["batched-mesh","geometry","validation","lifecycle"],"backgroundTag":null,"analyzedSha":"da05705fa31f02710c19772a2aa70c7454807f0c","analyzedAt":"2026-08-12T22:51:37.160Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}