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
- Normalize every shared attribute to the same itemSize and normalized value before adding.
- Re-create the mismatched attribute with the correct component count and normalized flag.
- 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
- Use a consistent itemSize and normalized flag for each shared attribute.
- Re-encode mismatched attributes (e.g. normalized bytes -> floats) before adding.
- Separate geometries with incompatible layouts into different batches.
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
- THREE.BatchedMesh: Added geometry missing "${ attributeName
- THREE.BatchedMesh: All geometries must consistently have "in
- THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometr
- THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instanc
- invalid length
AI-assisted analysis of mrdoob/three.js@da05705fa3 (2026-08-12).
Data as JSON: /api/errors/25822a8cb2a5c72a.
Report an issue: GitHub.