mrdoob/three.js · error · Error
THREE.BatchedMesh: Maximum geometry count reached.
Error message
THREE.BatchedMesh: Maximum geometry count reached.
What it means
Thrown by BatchedMesh.setGeometryAt() when the supplied geometryId is greater than or equal to the current _geometryCount. Geometry IDs are only valid in the range [0, _geometryCount), so passing an out-of-range, stale, or pre-allocation ID is treated as programmer error rather than silently ignored.
Source
Thrown at src/objects/BatchedMesh.js:718
return geometryId;
}
/**
* Replaces the geometry at the given ID with the provided geometry. Throws an error if there
* is not enough space reserved for geometry. Calling this will change all instances that are
* rendering that geometry.
*
* @param {number} geometryId - The ID of the geometry that should be replaced with the given geometry.
* @param {BufferGeometry} geometry - The new geometry.
* @return {number} The geometry ID.
*/
setGeometryAt( geometryId, geometry ) {
if ( geometryId >= this._geometryCount ) {
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.' );
View on GitHub (pinned to da05705fa3)
Solutions
- Always store and reuse the ID returned by addGeometry instead of inventing one.
- Guard the call: if (geometryId >= batchedMesh.geometryCount) return; before setGeometryAt.
- After deleteGeometry, discard any IDs you held for freed slots or re-map them.
- Use batchedMesh.geometryCount (the live count) as the loop bound, not the constructor capacity.
Example fix
// before batch.setGeometryAt( 0, newGeom ); // 0 may be invalid if geometry was deleted // after const id = batch.addGeometry( placeholderGeo ); batch.setGeometryAt( id, newGeom );
Defensive patterns
Strategy: validation
Validate before calling
if ( geometryId < batchedMesh.geometryCount ) {
batchedMesh.setGeometryAt( geometryId, geometry );
} Prevention
- Always store and reuse the ID returned by addGeometry; never invent IDs.
- Use batchedMesh.geometryCount (live count) as loop bounds, not the constructor capacity.
- After deleteGeometry, discard any held IDs for freed slots.
- Validate geometryId against geometryCount before setGeometryAt.
When it happens
Trigger: Calling batchedMesh.setGeometryAt(geometryId, geometry) with a geometryId that was never returned by addGeometry; using an ID after deleteGeometry freed and the count shrank; passing a raw integer constant instead of the stored ID; iterating IDs up to the constructor's maxGeometryCount rather than the live geometryCount.
Common situations: Hardcoding geometry IDs instead of storing addGeometry's return value; holding IDs across a deleteGeometry/compaction; off-by-one loops over geometry slots; confusing maxGeometryCount (capacity) with the live geometryCount.
Related errors
- THREE.BatchedMesh: Reserved space request exceeds the maximu
- THREE.BatchedMesh: Reserved space not large enough for provi
- THREE.BatchedMesh: Instance ids outside the range ${ maxInst
- THREE.BatchedMesh: Geometry vertex values are being used out
- THREE.BatchedMesh: Geometry index values are being used outs
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/3926e7d238fb0126.
Report an issue: GitHub.