mrdoob/three.js · error · Error

THREE.BatchedMesh: Maximum item count reached.

Error message

THREE.BatchedMesh: Maximum item count reached.

What it means

Thrown by BatchedMesh.addInstance() when `_instanceInfo.length >= maxInstanceCount` AND there are no freed ids available in `_availableInstanceIds`. The batch is statically sized by the maxInstanceCount constructor argument; once full (and with no deletions to recycle ids), no further instances can be added.

Source

Thrown at src/objects/BatchedMesh.js:568

		}

	}

	/**
	 * Adds a new instance to the batch using the geometry of the given ID and returns
	 * a new id referring to the new instance to be used by other functions.
	 *
	 * @param {number} geometryId - The ID of a previously added geometry via {@link BatchedMesh#addGeometry}.
	 * @return {number} The instance ID.
	 */
	addInstance( geometryId ) {

		const atCapacity = this._instanceInfo.length >= this.maxInstanceCount;

		// ensure we're not over geometry
		if ( atCapacity && this._availableInstanceIds.length === 0 ) {

			throw new Error( 'THREE.BatchedMesh: Maximum item count reached.' );

		}

		const instanceInfo = {
			visible: true,
			active: true,
			geometryIndex: geometryId,
		};

		let drawId = null;

		// Prioritize using previously freed instance ids
		if ( this._availableInstanceIds.length > 0 ) {

			this._availableInstanceIds.sort( ascIdSort );

			drawId = this._availableInstanceIds.shift();
			this._instanceInfo[ drawId ] = instanceInfo;

View on GitHub (pinned to da05705fa3)

Solutions

  1. Construct BatchedMesh with a maxInstanceCount large enough for the maximum expected instances (plus headroom).
  2. Recycle instances: call deleteInstance() for dead entities before adding new ones.
  3. If the cap is structurally wrong, rebuild the BatchedMesh with a larger maxInstanceCount (call setInstanceCount to grow it, or recreate).

Example fix

// before
const batch = new BatchedMesh( 100, vertexCount );
for ( let i = 0; i < 150; i ++ ) batch.addInstance( geomId ); // throws at 100

// after
const batch = new BatchedMesh( 200, vertexCount );
for ( let i = 0; i < 150; i ++ ) batch.addInstance( geomId );
Defensive patterns

Strategy: validation

Validate before calling

function canAddInstance( batch ) {
  const atCapacity = batch._instanceInfo.length >= batch.maxInstanceCount;
  return ! atCapacity || batch._availableInstanceIds.length > 0;
}

if ( ! canAddInstance( batch ) ) throw new Error( 'BatchedMesh is at capacity; delete instances or raise maxInstanceCount.' );

Type guard

const hasInstanceCapacity = ( batch ) => canAddInstance( batch );

Try / catch

try {
  batch.addInstance( geometryId );
} catch ( e ) {
  if ( /Maximum item count reached/.test( e.message ) ) {
    batch.deleteInstance( recycledId ); // free a slot then retry
    batch.addInstance( geometryId );
  } else throw e;
}

Prevention

When it happens

Trigger: Calling addInstance() more than maxInstanceCount times without deleting any; constructing BatchedMesh with too small a maxInstanceCount for the scene; deleting nothing and continuing to add.

Common situations: Underestimating instance count at construction; growing a scene beyond the pre-allocated batch size; spawning entities dynamically without freeing dead ones.

Related errors


AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12). Data as JSON: /api/errors/562b838a014aa187. Report an issue: GitHub.