mrdoob/three.js · error · Error

THREE.BatchedMesh: Instance ids outside the range ${ maxInst

Error message

THREE.BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.

What it means

Thrown by BatchedMesh.setInstanceCount() when you request a maxInstanceCount smaller than the number of instances currently in use. setInstanceCount can only shrink down to instanceInfo.length after popping trailing unused slots; if any active instance occupies an ID >= the requested count, shrinking is refused.

Source

Thrown at src/objects/BatchedMesh.js:1282

	 * @param {number} maxInstanceCount - The max number of individual instances that can be added and rendered by the batch.
	*/
	setInstanceCount( maxInstanceCount ) {

		// shrink the available instances as much as possible
		const availableInstanceIds = this._availableInstanceIds;
		const instanceInfo = this._instanceInfo;
		availableInstanceIds.sort( ascIdSort );
		while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length - 1 ) {

			instanceInfo.pop();
			availableInstanceIds.pop();

		}

		// throw an error if it can't be shrunk to the desired size
		if ( maxInstanceCount < instanceInfo.length ) {

			throw new Error( `THREE.BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.` );

		}

		// copy the multi draw counts
		const multiDrawCounts = new Int32Array( maxInstanceCount );
		const multiDrawStarts = new Int32Array( maxInstanceCount );
		copyArrayContents( this._multiDrawCounts, multiDrawCounts );
		copyArrayContents( this._multiDrawStarts, multiDrawStarts );

		this._multiDrawCounts = multiDrawCounts;
		this._multiDrawStarts = multiDrawStarts;
		this._maxInstanceCount = maxInstanceCount;

		// update texture data for instance sampling
		const indirectTexture = this._indirectTexture;
		const matricesTexture = this._matricesTexture;
		const colorsTexture = this._colorsTexture;

View on GitHub (pinned to da05705fa3)

Solutions

  1. Delete or compact instances so the highest in-use ID is below maxInstanceCount before calling setInstanceCount.
  2. Call deleteGeometry/addInstance in an order that keeps IDs dense, or re-create the BatchedMesh at the desired capacity.
  3. Query the actual required count (highest active instance id + 1) and only shrink to that floor.
  4. If you must shrink aggressively, build a new BatchedMesh and migrate active instances.

Example fix

// before
batch.addInstance( 5, geoId, matrix ); // high id in use
batch.setInstanceCount( 3 ); // throws: id 5 >= 3

// after
batch.deleteInstance( 5 );
batch.addInstance( 1, geoId, matrix ); // re-add into a low slot
batch.setInstanceCount( 3 );
Defensive patterns

Strategy: validation

Validate before calling

// Compute the floor: highest in-use instance id + 1.
let highest = -1;
for ( let i = 0; i < batchedMesh._instanceInfo.length; i++ ) {
  if ( batchedMesh._instanceInfo[ i ].active ) highest = i;
}
const floor = highest + 1;
if ( newCount >= floor ) batchedMesh.setInstanceCount( newCount );

Prevention

When it happens

Trigger: Calling batchedMesh.setInstanceCount(n) where n is less than the highest in-use instance ID + 1. Common when instances were added with addInstance up to high IDs and you then attempt to lower the capacity without first deleting the high-id instances.

Common situations: Trying to free memory by lowering instance capacity while instances still reference those high slots; computing the new count from a live-instance count that excludes still-allocated high IDs.

Related errors


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