{"record":{"id":"ddeb86f8ab802a59","repo":"mrdoob/three.js","slug":"three-batchedmesh-reserved-space-request-exceeds","errorCode":null,"errorMessage":"THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.","messagePattern":"THREE\\.BatchedMesh: Reserved space request exceeds the maximum buffer size\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/objects/BatchedMesh.js","lineNumber":672,"sourceCode":"\t\tgeometryInfo.vertexStart = this._nextVertexStart;\n\t\tgeometryInfo.reservedVertexCount = reservedVertexCount === - 1 ? geometry.getAttribute( 'position' ).count : reservedVertexCount;\n\n\t\tconst index = geometry.getIndex();\n\t\tconst hasIndex = index !== null;\n\t\tif ( hasIndex ) {\n\n\t\t\tgeometryInfo.indexStart = this._nextIndexStart;\n\t\t\tgeometryInfo.reservedIndexCount = reservedIndexCount === - 1 ? index.count : reservedIndexCount;\n\n\t\t}\n\n\t\tif (\n\t\t\tgeometryInfo.indexStart !== - 1 &&\n\t\t\tgeometryInfo.indexStart + geometryInfo.reservedIndexCount > this._maxIndexCount ||\n\t\t\tgeometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount\n\t\t) {\n\n\t\t\tthrow new Error( 'THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.' );\n\n\t\t}\n\n\t\t// update id\n\t\tlet geometryId;\n\t\tif ( this._availableGeometryIds.length > 0 ) {\n\n\t\t\tthis._availableGeometryIds.sort( ascIdSort );\n\n\t\t\tgeometryId = this._availableGeometryIds.shift();\n\t\t\tgeometryInfoList[ geometryId ] = geometryInfo;\n\n\n\t\t} else {\n\n\t\t\tgeometryId = this._geometryCount;\n\t\t\tthis._geometryCount ++;\n\t\t\tgeometryInfoList.push( geometryInfo );","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/mrdoob/three.js/blob/da05705fa31f02710c19772a2aa70c7454807f0c/src/objects/BatchedMesh.js#L654-L690","documentation":"Thrown by BatchedMesh.addGeometry() when the requested vertex/index reservation does not fit in the backing buffers. AddGeometry reserves a contiguous run of the shared attribute/index buffer; if the running start pointer plus the requested reservation exceeds _maxVertexCount or _maxIndexCount, the reservation is rejected. Note operator precedence: the vertex overflow is always checked, while the index overflow is only checked when the geometry has an index.","triggerScenarios":"Calling batchedMesh.addGeometry(geometry, reservedVertexCount, reservedIndexCount) where reservedVertexCount defaults to geometry's position count (or a custom value) that, combined with _nextVertexStart, exceeds maxVertexCount; OR an indexed geometry whose _nextIndexStart + reservedIndexCount exceeds maxIndexCount. Also triggered after many addGeometry calls have filled the buffer.","commonSituations":"Constructing BatchedMesh with a too-small vertexCount/indexCount for the assets you load; loading GLTF models whose geometry is larger than the default reservation; growing content at runtime without pre-sizing the batch; forgetting that reservedVertexCount=-1 uses the full attribute count, not a small default.","solutions":["Construct BatchedMesh with larger maxVertexCount/maxIndexCount sized to the sum of all geometries you will add (plus headroom).","Pass an explicit reservedVertexCount/reservedIndexCount to addGeometry sized to the largest geometry variant you will swap in later, instead of relying on the -1 default.","Before adding, verify (batchedMesh.geometrySize) or track current usage and call setGeometrySize() to grow the buffers when near capacity.","If reservations are fragmented, remove unused geometries (deleteGeometry) to reclaim their slots before adding new ones."],"exampleFix":"// before\nconst batch = new THREE.BatchedMesh( 10, 1000, 1000 ); // too small for real assets\nbatch.addGeometry( loadedMesh.geometry ); // throws when verts > 1000\n\n// after\nconst batch = new THREE.BatchedMesh( 10, 200000, 400000 );\nbatch.addGeometry( loadedMesh.geometry, loadedMesh.geometry.attributes.position.count, loadedMesh.geometry.index ? loadedMesh.geometry.index.count : 0 );","handlingStrategy":"validation","validationCode":"// Before addGeometry, confirm the reservation fits.\nfunction canAddGeometry( batchedMesh, geometry, reservedVertexCount = -1, reservedIndexCount = -1 ) {\n  const posCount = geometry.attributes.position.count;\n  const resV = reservedVertexCount === -1 ? posCount : reservedVertexCount;\n  const idx = geometry.getIndex();\n  const nextV = batchedMesh._nextVertexStart; // or track externally\n  if ( nextV + resV > batchedMesh.vertexCount ) return false;\n  if ( idx ) {\n    const resI = reservedIndexCount === -1 ? idx.count : reservedIndexCount;\n    if ( batchedMesh._nextIndexStart + resI > batchedMesh.indexCount ) return false;\n  }\n  return true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-size BatchedMesh capacity to the summed vertex/index counts of all planned geometries plus headroom.","Always pass explicit reservedVertexCount/reservedIndexCount sized to the largest variant you will swap in.","Track running usage externally and call setGeometrySize() to grow before exhaustion.","Reclaim slots via deleteGeometry before adding new geometries when the buffer is fragmented."],"tags":["batchedmesh","buffer-overflow","geometry","resource-allocation"],"backgroundTag":null,"analyzedSha":"da05705fa31f02710c19772a2aa70c7454807f0c","analyzedAt":"2026-08-12T22:51:37.160Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}