mrdoob/three.js · error · Error

THREE.WebGLAttributes: The size of the buffer attribute's ar

Error message

THREE.WebGLAttributes: The size of the buffer attribute's array buffer does not match the original size. Resizing buffer attributes is not supported.

What it means

Thrown by WebGLAttributes.update() when a BufferAttribute's version was bumped (marking it dirty) but its underlying array buffer's byteLength changed since the GPU buffer was first created. WebGL buffers are allocated at a fixed size; the renderer does not silently reallocate, so a size change after creation is rejected as a programming error.

Source

Thrown at src/renderers/webgl/WebGLAttributes.js:214

				} );

			}

			return;

		}

		const data = buffers.get( attribute );

		if ( data === undefined ) {

			buffers.set( attribute, createBuffer( attribute, bufferType ) );

		} else if ( data.version < attribute.version ) {

			if ( data.size !== attribute.array.byteLength ) {

				throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' );

			}

			updateBuffer( data.buffer, attribute, bufferType );

			data.version = attribute.version;

		}

	}

	return {

		get: get,
		remove: remove,
		update: update

	};

View on GitHub (pinned to da05705fa3)

Solutions

  1. Replace the attribute entirely when the size changes: `geometry.setAttribute('position', new BufferAttribute(newArray, 3))`.
  2. Pre-allocate a maximum-size buffer and update a subset (use updateRanges) rather than resizing.
  3. Dispose the geometry/attribute and rebuild it when the data size changes.
  4. If shrinking temporarily, keep the original buffer length and only mark the used range dirty.

Example fix

// before - reassign a larger array on the same attribute
attr.array = new Float32Array(newData); // larger byteLength
attr.version++; // triggers update() -> throws

// after - replace the attribute
geom.setAttribute('position', new BufferAttribute(new Float32Array(newData), 3));
Defensive patterns

Strategy: validation

Validate before calling

function setOrUpdateAttribute(geometry, name, array, itemSize) {
  const existing = geometry.getAttribute(name);
  if (!existing || existing.array.byteLength !== array.byteLength) {
    geometry.setAttribute(name, new THREE.BufferAttribute(array, itemSize));
  } else {
    existing.array.set(array);
    existing.needsUpdate = true;
  }
}

Type guard

function canUpdateInPlace(attribute, newArray) {
  return attribute && attribute.array.byteLength === newArray.byteLength;
}

Prevention

When it happens

Trigger: Mutating `attribute.array` to a differently-sized typed array (e.g. pushing/popping and reassigning a new Float32Array) then bumping `attribute.version`, rather than replacing the BufferAttribute on the geometry.

Common situations: Dynamic line/particle systems that grow or shrink over time. Reassigning `attribute.array = new Float32Array(newLength)` and `attribute.needsUpdate = true` instead of replacing the attribute. Geometry pooling where the same attribute object is repurposed for different sizes.

Related errors


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