mrdoob/three.js · error · Error

THREE.BatchedMesh: All attributes must have a consistent ite

Error message

THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.

What it means

Thrown by BatchedMesh._validateGeometry() when a shared attribute has a mismatched `itemSize` or `normalized` flag between the added geometry and the batch's combined geometry. Even if the attribute exists, its component count and normalization must match exactly.

Source

Thrown at src/objects/BatchedMesh.js:440

		if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {

			throw new Error( 'THREE.BatchedMesh: All geometries must consistently have "index".' );

		}

		for ( const attributeName in batchGeometry.attributes ) {

			if ( ! geometry.hasAttribute( attributeName ) ) {

				throw new Error( `THREE.BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );

			}

			const srcAttribute = geometry.getAttribute( attributeName );
			const dstAttribute = batchGeometry.getAttribute( attributeName );
			if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {

				throw new Error( 'THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );

			}

		}

	}

	/**
	 * Validates the instance defined by the given ID.
	 *
	 * @param {number} instanceId - The instance to validate.
	 */
	validateInstanceId( instanceId ) {

		const instanceInfo = this._instanceInfo;
		if ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {

			throw new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );

View on GitHub (pinned to da05705fa3)

Solutions

  1. Normalize every shared attribute to the same itemSize and normalized value before adding.
  2. Re-create the mismatched attribute with the correct component count and normalized flag.
  3. Separate geometries with incompatible attribute layouts into different BatchedMesh instances.

Example fix

// before
// batch 'color' is itemSize 3, float
batch.addGeometry( geomWithByteColor ); // itemSize 4, normalized

// after
geomWithByteColor.setAttribute( 'color', new Float32BufferAttribute( geomWithByteColor.attributes.color.array.filter((_,i)=>i%4<3), 3 ) );
batch.addGeometry( geomWithByteColor );
Defensive patterns

Strategy: validation

Validate before calling

function assertAttributeLayoutMatches( batch, geometry ) {
  for ( const name in batch.geometry.attributes ) {
    const a = geometry.getAttribute( name ), b = batch.geometry.getAttribute( name );
    if ( a.itemSize !== b.itemSize || a.normalized !== b.normalized ) {
      throw new Error( `Attribute '${ name }' layout mismatch (itemSize/normalized).` );
    }
  }
}

Type guard

const attributeLayoutsMatch = ( batch, geometry ) => Object.keys( batch.geometry.attributes ).every( ( n ) => {
  const a = geometry.getAttribute( n ), b = batch.geometry.getAttribute( n );
  return a.itemSize === b.itemSize && a.normalized === b.normalized;
} );

Prevention

When it happens

Trigger: Adding a geometry whose 'uv' is itemSize 2 but the batch's is itemSize 4; mixing normalized (e.g. normalized color attributes) with non-normalized ones; a custom attribute with a different component count than the batch's first geometry.

Common situations: Batching geometries with different vertex layouts; color attributes where some are normalized byte arrays and others are float; uv1 vs uv0 confusion; loaded glTF geometries with different attribute encodings.

Related errors


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