{"record":{"id":"0667f7ca2bf59d60","repo":"BabylonJS/Babylon.js","slug":"draco-decoder-module-is-not-available-0667f7","errorCode":null,"errorMessage":"Draco: Decoder module is not available","messagePattern":"Draco: Decoder module is not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Meshes/Compression/dracoDecoder.ts","lineNumber":220,"sourceCode":"                        resultIndices = indices;\r\n                    },\r\n                    (kind, data, size, byteOffset, byteStride, normalized) => {\r\n                        resultAttributes.push({\r\n                            kind,\r\n                            data,\r\n                            size,\r\n                            byteOffset,\r\n                            byteStride,\r\n                            normalized,\r\n                        });\r\n                    }\r\n                );\r\n\r\n                return { indices: resultIndices!, attributes: resultAttributes, totalVertices: numPoints };\r\n            });\r\n        }\r\n\r\n        throw new Error(\"Draco: Decoder module is not available\");\r\n    }\r\n\r\n    /**\r\n     * Decode Draco compressed mesh data to Babylon geometry.\r\n     * @param name The name to use when creating the geometry\r\n     * @param scene The scene to use when creating the geometry\r\n     * @param data The ArrayBuffer or ArrayBufferView of the Draco compressed data\r\n     * @param attributes A map of attributes from vertex buffer kinds to Draco unique ids\r\n     * @returns A promise that resolves with the decoded geometry\r\n     */\r\n    public async decodeMeshToGeometryAsync(name: string, scene: Scene, data: ArrayBuffer | ArrayBufferView, attributes?: { [kind: string]: number }): Promise<Geometry> {\r\n        const meshData = await this.decodeMeshToMeshDataAsync(data, attributes);\r\n        const geometry = new Geometry(name, scene);\r\n        if (meshData.indices) {\r\n            geometry.setIndices(meshData.indices);\r\n        }\r\n        for (const attribute of meshData.attributes) {\r\n            geometry.setVerticesBuffer(\r","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Meshes/Compression/dracoDecoder.ts#L202-L238","documentation":"DracoDecoder.decodeMeshToMeshDataAsync throws when `dracoCompression.Configuration.decoder` is not marked available (no decoder module configured/loaded), so there is no DracoDecoderModule instance to decode with. It guards the decode entry point on the main thread before dispatching to workers.","triggerScenarios":"Calling `DracoCompression.DecodeMeshToMeshDataAsync` (or `.decodeMeshToMeshDataAsync`) while `DracoCompression.Configuration.decoder` is undefined/null or its `.available` flag is false.","commonSituations":"Forgetting to load the Draco decoder script (default CDN unreachable/offline PWA), stripping the decoder config in bundled builds, or an awaited decode running before the configuration object finished loading the WASM.","solutions":["Configure the decoder before use: `DracoCompression.Configuration.decoder = { url: \"<path>/draco_decoder.js\", wasmUrl: ... }` and ensure the URL loads.","Preload/await the decoder module (e.g. trigger an init or `whenReadyAsync`) before decoding any Draco data.","Check `DracoCompression.Configuration.decoder?.available` before calling decode and load on demand if false.","Fallback: skip Draco decode path if the module can't load (decode uncompressed geometry instead)."],"exampleFix":"// before\nconst data = await DracoCompression.DecodeMeshToMeshDataAsync(drcData);\n\n// after\nif (!DracoCompression.Configuration.decoder) {\n    DracoCompression.Configuration.decoder = { url: \"https://cdn.babylonjs.com/draco/draco_decoder.js\" };\n}\nawait firstObservedPromise; // ensure decoder module finished loading\nconst data = await DracoCompression.DecodeMeshToMeshDataAsync(drcData);","handlingStrategy":"validation","validationCode":"if (!DracoCompression.Configuration.decoder || !DracoCompression.Configuration.decoder.available) {\n    DracoCompression.Configuration.decoder = { url: \"https://cdn.babylonjs.com/draco/draco_decoder.js\" };\n    await ensureDecoderLoaded();\n}","typeGuard":"function canDecodeDraco(): boolean {\n    return !!DracoCompression.Configuration.decoder?.available;\n}","tryCatchPattern":"try {\n    return await DracoCompression.DecodeMeshToMeshDataAsync(data);\n} catch (e) {\n    if (e instanceof Error && e.message.includes(\"Decoder module is not available\")) {\n        await loadDracoDecoder();\n        return await DracoCompression.DecodeMeshToMeshDataAsync(data);\n    }\n    throw e;\n}","preventionTips":["Set decoder config once in a bootstrap module imported before any Draco asset loads","Preload the decoder during app startup/loading screen","Gate decode calls behind a decoder-ready promise","Monitor failed WASM/script fetches (offline/CSP) in error reporting"],"tags":["draco","decoder","initialization","compression"],"backgroundTag":"module-not-initialized","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}