BabylonJS/Babylon.js · error · Error

${context}: Primitives do not have the same number of target

Error message

${context}: Primitives do not have the same number of targets

What it means

For multi-primitive meshes with morph targets, the glTF spec requires all primitives to have the same number of morph targets. The loader records the first primitive's target count on node._numMorphTargets and throws if a later primitive's targets.length differs, since Babylon MorphTargetManager cannot represent inconsistent counts per mesh.

Source

Thrown at packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts:1323

            if (accessor.type === AccessorType.VEC4) {
                babylonMesh.hasVertexAlpha = true;
            }
        });

        return Promise.all(promises).then(() => {
            return babylonGeometry;
        });
    }

    private _createMorphTargets(context: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, babylonMesh: Mesh): void {
        if (!primitive.targets || !this._parent.loadMorphTargets) {
            return;
        }

        if (node._numMorphTargets == undefined) {
            node._numMorphTargets = primitive.targets.length;
        } else if (primitive.targets.length !== node._numMorphTargets) {
            throw new Error(`${context}: Primitives do not have the same number of targets`);
        }

        const targetNames = mesh.extras ? mesh.extras.targetNames : null;

        this._babylonScene._blockEntityCollection = !!this._assetContainer;
        babylonMesh.morphTargetManager = new MorphTargetManager(this._babylonScene);
        babylonMesh.morphTargetManager._parentContainer = this._assetContainer;
        this._babylonScene._blockEntityCollection = false;

        babylonMesh.morphTargetManager.areUpdatesFrozen = true;

        for (let index = 0; index < primitive.targets.length; index++) {
            const weight = node.weights ? node.weights[index] : mesh.weights ? mesh.weights[index] : 0;
            const name = targetNames ? targetNames[index] : `morphTarget${index}`;
            babylonMesh.morphTargetManager.addTarget(new MorphTarget(name, weight, babylonMesh.getScene()));
            // TODO: tell the target whether it has positions, normals, tangents
        }
    }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Fix the asset so every primitive in the mesh declares the same number of targets (pad missing ones with zero-weight targets)
  2. Use gltf-transform or a script to normalize morph target counts across primitives
  3. Re-export from the DCC tool ensuring morph targets apply to the whole mesh
  4. Split the mesh into separate meshes if the primitives genuinely need different morph target counts

Example fix

// before (in .gltf)
// primitives: [ {targets:[t0,t1]}, {targets:[t0,t1,t2]} ]
// after
// primitives: [ {targets:[t0,t1]}, {targets:[t0,t1,zeroTarget]} ] // equal counts
Defensive patterns

Strategy: validation

Validate before calling

// Verify all primitives in each mesh have equal morph target counts
for (const mesh of gltf.meshes ?? []) {
  const counts = (mesh.primitives ?? []).map(p => (p.targets ?? []).length);
  if (new Set(counts).size > 1) {
    throw new Error(`Mesh '${mesh.name}' primitives have inconsistent morph target counts: ${counts}`);
  }
}

Type guard

function morphTargetCountsConsistent(mesh) {
  const counts = (mesh.primitives ?? []).map(p => (p.targets ?? []).length);
  return new Set(counts).size <= 1;
}

Try / catch

try {
  await loader.loadAsync(url);
} catch (e) {
  if (e.message.includes("do not have the same number of targets")) {
    console.error("Normalize morph target counts across primitives before loading");
  } else throw e;
}

Prevention

When it happens

Trigger: Loading a glTF mesh where primitive[0] has, say, 2 morph targets but primitive[1] has 3 — commonly from hand-merged meshes or exporter bugs.

Common situations: Merging meshes in asset pipelines where only some parts got morph targets; custom exporters that emit per-primitive morph data inconsistently; hand-edited glTF files.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/7552c6e568ac1fbb. Report an issue: GitHub.