mrdoob/three.js · error · Error
THREE.BatchedMesh: Reserved space not large enough for provi
Error message
THREE.BatchedMesh: Reserved space not large enough for provided geometry.
What it means
Thrown by BatchedMesh.setGeometryAt() when the new geometry needs more vertices or indices than were reserved at addGeometry() time. Each geometry slot has a fixed reservedVertexCount/reservedIndexCount; setGeometryAt refuses to write past that reservation even if the backing buffer has spare room.
Source
Thrown at src/objects/BatchedMesh.js:735
throw new Error( 'THREE.BatchedMesh: Maximum geometry count reached.' );
}
this._validateGeometry( geometry );
const batchGeometry = this.geometry;
const hasIndex = batchGeometry.getIndex() !== null;
const dstIndex = batchGeometry.getIndex();
const srcIndex = geometry.getIndex();
const geometryInfo = this._geometryInfo[ geometryId ];
if (
hasIndex &&
srcIndex.count > geometryInfo.reservedIndexCount ||
geometry.attributes.position.count > geometryInfo.reservedVertexCount
) {
throw new Error( 'THREE.BatchedMesh: Reserved space not large enough for provided geometry.' );
}
// copy geometry buffer data over
const vertexStart = geometryInfo.vertexStart;
const reservedVertexCount = geometryInfo.reservedVertexCount;
geometryInfo.vertexCount = geometry.getAttribute( 'position' ).count;
for ( const attributeName in batchGeometry.attributes ) {
// copy attribute data
const srcAttribute = geometry.getAttribute( attributeName );
const dstAttribute = batchGeometry.getAttribute( attributeName );
copyAttributeData( srcAttribute, dstAttribute, vertexStart );
// fill the rest in with zeroes
const itemSize = srcAttribute.itemSize;
for ( let i = srcAttribute.count, l = reservedVertexCount; i < l; i ++ ) {View on GitHub (pinned to da05705fa3)
Solutions
- When calling addGeometry, reserve enough space for the LARGEST geometry you will ever place in that slot: addGeometry(placeholder, maxVerts, maxIndices).
- If the slot is too small, deleteGeometry then addGeometry again with a larger reservation to get a fresh ID.
- Pre-measure all candidate geometries and pass the max as the reservation before any setGeometryAt.
- Track per-slot reservation and validate geometry.attributes.position.count and geometry.index.count against it before calling setGeometryAt.
Example fix
// before const id = batch.addGeometry( lowLodGeo ); // reserved = lowLod size batch.setGeometryAt( id, highLodGeo ); // throws: highLod > reserved // after const maxVerts = Math.max( lowLodGeo.attributes.position.count, highLodGeo.attributes.position.count ); const maxIdx = Math.max( lowLodGeo.index.count, highLodGeo.index.count ); const id = batch.addGeometry( lowLodGeo, maxVerts, maxIdx ); batch.setGeometryAt( id, highLodGeo );
Defensive patterns
Strategy: validation
Validate before calling
const info = batchedMesh.geometryInfo[ geometryId ]; const fitsV = geometry.attributes.position.count <= info.reservedVertexCount; const idx = geometry.getIndex(); const fitsI = !idx || ( batchedMesh.geometry.index && idx.count <= info.reservedIndexCount ); if ( fitsV && fitsI ) batchedMesh.setGeometryAt( geometryId, geometry );
Prevention
- Reserve for the LARGEST geometry variant at addGeometry time.
- Measure all candidate geometries up front and pass the max as the reservation.
- If a slot is too small, deleteGeometry and re-add with a larger reservation.
- Validate position.count and index.count against the slot reservation before setGeometryAt.
When it happens
Trigger: addGeometry was called with a small reservedVertexCount/reservedIndexCount (or the default sized to a placeholder), then setGeometryAt replaces it with a geometry whose position.count or index.count exceeds the reservation. Replacing a low-LOD mesh with a high-LOD variant in the same slot.
Common situations: LOD swapping where the high-detail mesh is larger than the initial reservation; loading async geometry where the final size was unknown at reservation time and defaulted to -1 (the placeholder's size); procedural geometry that grew.
Related errors
- THREE.BatchedMesh: Reserved space request exceeds the maximu
- THREE.BufferAttribute: array should be a Typed Array.
- THREE.BatchedMesh: All geometries must consistently have "in
- THREE.BatchedMesh: Added geometry missing "${ attributeName
- THREE.BatchedMesh: All attributes must have a consistent ite
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/e331efe93c75be2a.
Report an issue: GitHub.