{"record":{"id":"7552c6e568ac1fbb","repo":"BabylonJS/Babylon.js","slug":"context-primitives-do-not-have-the-same-number","errorCode":null,"errorMessage":"${context}: Primitives do not have the same number of targets","messagePattern":"(.+?): Primitives do not have the same number of targets","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts","lineNumber":1323,"sourceCode":"            if (accessor.type === AccessorType.VEC4) {\r\n                babylonMesh.hasVertexAlpha = true;\r\n            }\r\n        });\r\n\r\n        return Promise.all(promises).then(() => {\r\n            return babylonGeometry;\r\n        });\r\n    }\r\n\r\n    private _createMorphTargets(context: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, babylonMesh: Mesh): void {\r\n        if (!primitive.targets || !this._parent.loadMorphTargets) {\r\n            return;\r\n        }\r\n\r\n        if (node._numMorphTargets == undefined) {\r\n            node._numMorphTargets = primitive.targets.length;\r\n        } else if (primitive.targets.length !== node._numMorphTargets) {\r\n            throw new Error(`${context}: Primitives do not have the same number of targets`);\r\n        }\r\n\r\n        const targetNames = mesh.extras ? mesh.extras.targetNames : null;\r\n\r\n        this._babylonScene._blockEntityCollection = !!this._assetContainer;\r\n        babylonMesh.morphTargetManager = new MorphTargetManager(this._babylonScene);\r\n        babylonMesh.morphTargetManager._parentContainer = this._assetContainer;\r\n        this._babylonScene._blockEntityCollection = false;\r\n\r\n        babylonMesh.morphTargetManager.areUpdatesFrozen = true;\r\n\r\n        for (let index = 0; index < primitive.targets.length; index++) {\r\n            const weight = node.weights ? node.weights[index] : mesh.weights ? mesh.weights[index] : 0;\r\n            const name = targetNames ? targetNames[index] : `morphTarget${index}`;\r\n            babylonMesh.morphTargetManager.addTarget(new MorphTarget(name, weight, babylonMesh.getScene()));\r\n            // TODO: tell the target whether it has positions, normals, tangents\r\n        }\r\n    }\r","sourceCodeStart":1305,"sourceCodeEnd":1341,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/loaders/src/glTF/2.0/glTFLoader.pure.ts#L1305-L1341","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the asset so every primitive in the mesh declares the same number of targets (pad missing ones with zero-weight targets)","Use gltf-transform or a script to normalize morph target counts across primitives","Re-export from the DCC tool ensuring morph targets apply to the whole mesh","Split the mesh into separate meshes if the primitives genuinely need different morph target counts"],"exampleFix":"// before (in .gltf)\n// primitives: [ {targets:[t0,t1]}, {targets:[t0,t1,t2]} ]\n// after\n// primitives: [ {targets:[t0,t1]}, {targets:[t0,t1,zeroTarget]} ] // equal counts","handlingStrategy":"validation","validationCode":"// Verify all primitives in each mesh have equal morph target counts\nfor (const mesh of gltf.meshes ?? []) {\n  const counts = (mesh.primitives ?? []).map(p => (p.targets ?? []).length);\n  if (new Set(counts).size > 1) {\n    throw new Error(`Mesh '${mesh.name}' primitives have inconsistent morph target counts: ${counts}`);\n  }\n}","typeGuard":"function morphTargetCountsConsistent(mesh) {\n  const counts = (mesh.primitives ?? []).map(p => (p.targets ?? []).length);\n  return new Set(counts).size <= 1;\n}","tryCatchPattern":"try {\n  await loader.loadAsync(url);\n} catch (e) {\n  if (e.message.includes(\"do not have the same number of targets\")) {\n    console.error(\"Normalize morph target counts across primitives before loading\");\n  } else throw e;\n}","preventionTips":["Apply morph targets to the whole mesh in the DCC tool, not per-part","Normalize target counts with a gltf-transform script in the asset pipeline"],"tags":["gltf","morph-targets","malformed-asset"],"backgroundTag":"gltf-invalid-asset-structure","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}