{"record":{"id":"49b4ea65ddc1702d","repo":"BabylonJS/Babylon.js","slug":"draco-cannot-exclude-position-attribute-from-enco","errorCode":null,"errorMessage":"Draco: Cannot exclude position attribute from encoding.","messagePattern":"Draco: Cannot exclude position attribute from encoding\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Meshes/Compression/dracoEncoder.ts","lineNumber":65,"sourceCode":"        indices = (AreIndices32Bits(indices, indices.length) ? Uint32Array : Uint16Array).from(indices);\r\n    }\r\n\r\n    return indices;\r\n}\r\n\r\n/**\r\n * Get relevant information about the geometry's vertex attributes for Draco encoding. Eventually used for each attribute as\r\n * `AddFloatAttribute(mesh: Mesh, attribute: number, count: number, itemSize: number, array: TypedArray)`\r\n * where `attribute = EncoderModule[<dracoAttribute>]`, `itemSize = <size>`, `array = <data>`, and count is the number of position vertices.\r\n * @internal\r\n */\r\nfunction PrepareAttributesForDraco(input: Mesh | Geometry, excludedAttributes?: string[]): Array<IDracoAttributeData> {\r\n    const attributes: Array<IDracoAttributeData> = [];\r\n\r\n    for (const kind of input.getVerticesDataKinds()) {\r\n        if (excludedAttributes?.includes(kind)) {\r\n            if (kind === VertexBuffer.PositionKind) {\r\n                throw new Error(\"Draco: Cannot exclude position attribute from encoding.\");\r\n            }\r\n            continue;\r\n        }\r\n\r\n        // Convert number[] to typed array, if needed.\r\n        const vertexBuffer = input.getVertexBuffer(kind)!;\r\n        const size = vertexBuffer.getSize();\r\n        const data = GetTypedArrayData(vertexBuffer.getData()!, size, vertexBuffer.type, vertexBuffer.byteOffset, vertexBuffer.byteStride, input.getTotalVertices(), true);\r\n        attributes.push({ kind: kind, dracoName: GetDracoAttributeName(kind), size: size, data: data });\r\n    }\r\n\r\n    return attributes;\r\n}\r\n\r\nconst DefaultEncoderOptions: IDracoEncoderOptions = {\r\n    decodeSpeed: 5,\r\n    encodeSpeed: 5,\r\n    method: \"MESH_EDGEBREAKER_ENCODING\",\r","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Meshes/Compression/dracoEncoder.ts#L47-L83","documentation":"Draco encoding cannot represent a mesh without positions, so `PrepareAttributesForDraco` throws if the `excludedAttributes` option lists VertexBuffer.PositionKind. Every other attribute kind may be excluded, but the position attribute is mandatory for the encoder.","triggerScenarios":"Calling `DracoEncoder.encodeMeshAsync(mesh, { excludedAttributes: [VertexBuffer.PositionKind] })`, or passing an exclusion list built dynamically (e.g. excluding all non-essential kinds) that happens to include \"position\".","commonSituations":"Trying to shrink files aggressively by excluding attributes; copying an exclusion list (like [\"normal\",\"uv\",\"position\"]) from another encoder config; or a generic \"exclude all except index\" pipeline that wrongly includes position.","solutions":["Remove VertexBuffer.PositionKind (\"position\") from the excludedAttributes array.","Filter exclusions programmatically: `excludedAttributes.filter(k => k !== VertexBuffer.PositionKind)`.","If the mesh truly shouldn't encode positions, don't use Draco encoding for it."],"exampleFix":"// before\nawait encoder.encodeMeshAsync(mesh, { excludedAttributes: [VertexBuffer.PositionKind, VertexBuffer.NormalKind] });\n\n// after\nawait encoder.encodeMeshAsync(mesh, { excludedAttributes: [VertexBuffer.NormalKind] });","handlingStrategy":"validation","validationCode":"const excluded = (opts.excludedAttributes ?? []).filter(k => k !== VertexBuffer.PositionKind);\nawait encoder.encodeMeshAsync(mesh, { ...opts, excludedAttributes: excluded });","typeGuard":"function exclusionsAreValid(excluded?: string[]): boolean {\n    return !excluded?.includes(VertexBuffer.PositionKind);\n}","tryCatchPattern":"try {\n    return await encoder.encodeMeshAsync(mesh, options);\n} catch (e) {\n    if (e instanceof Error && e.message.includes(\"Cannot exclude position attribute\")) {\n        options.excludedAttributes = options.excludedAttributes?.filter(k => k !== VertexBuffer.PositionKind);\n        return await encoder.encodeMeshAsync(mesh, options);\n    }\n    throw e;\n}","preventionTips":["Never include VertexBuffer.PositionKind in excludedAttributes","Sanitize exclusion lists that are built dynamically or come from user config","Add a unit test asserting position is never excluded in your encoder wrapper"],"tags":["draco","encoder","validation","vertex-attributes"],"backgroundTag":"invalid-attribute-configuration","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}