BabylonJS/Babylon.js · error · Error
Draco: Decoder module is not available
Error message
Draco: Decoder module is not available
What it means
In the Draco decoder worker, a "decodeMesh" message was received but no decoder module was ever initialized: `decoderPromise` is null. The worker requires an "init" message (which calls DracoDecoderModule) before any decode request. The library throws to prevent decoding with an uninitialized WASM decoder.
Source
Thrown at packages/dev/core/src/Meshes/Compression/dracoCompressionWorker.ts:338
export function DecoderWorkerFunction(): void {
let decoderPromise: PromiseLike<DecoderModule> | undefined;
onmessage = (event) => {
const message = event.data;
switch (message.id) {
case "init": {
// if URL is provided then load the script. Otherwise expect the script to be loaded already
if (message.url) {
importScripts(message.url);
}
const initDecoderObject = message.wasmBinary ? { wasmBinary: message.wasmBinary } : {};
decoderPromise = DracoDecoderModule(initDecoderObject);
postMessage({ id: "initDone" });
break;
}
case "decodeMesh": {
if (!decoderPromise) {
throw new Error("Draco: Decoder module is not available");
}
// eslint-disable-next-line github/no-then
decoderPromise.then((decoder) => {
const numPoints = DecodeMesh(
decoder,
message.dataView,
message.attributes,
(indices) => {
postMessage({ id: "indices", data: indices }, [indices.buffer]);
},
(kind, data, size, offset, stride, normalized) => {
postMessage({ id: "attribute", kind, data, size, byteOffset: offset, byteStride: stride, normalized }, [data.buffer]);
}
);
postMessage({ id: "decodeMeshDone", totalVertices: numPoints });
});
break;
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure the Draco decoder is configured before decoding: set `dracoCompression.Configuration.decoder = { url: ... }` (or use default CDN) and await initialization (`DracoCompression.Default...` ready) prior to `_loadGroundAsync`/decode calls.
- Verify the decoder URL is reachable (network tab) and CORS/CSP allows the WASM script and .wasm fetch.
- Check that the worker receives the init message before decodeMesh; avoid manually posting worker messages out of order.
- Catch the worker error and re-queue the decode after re-initializing the decoder module.
Example fix
// before
mesh.convertToFlatShadedMesh();
DracoCompression.DecodeMeshToMeshDataAsync(data);
// after
DracoCompression.Configuration.decoder = { url: "https://cdn.babylonjs.com/draco/draco_decoder.js" };
await DracoCompression._GetDefaultSupported... // or simply await scene.whenReadyAsync();
const meshData = await DracoCompression.DecodeMeshToMeshDataAsync(data); Defensive patterns
Strategy: validation
Validate before calling
if (!DracoCompression.Configuration.decoder?.available) {
// load decoder config / await initialization before posting decodeMesh
throw new SkipDecode();
} Type guard
function decoderReady(): boolean {
return !!DracoCompression.Configuration.decoder?.available;
} Try / catch
try {
await worker.decode(view);
} catch (e) {
if (String(e?.message).includes("Decoder module is not available")) {
await initDecoder();
return worker.decode(view); // retry once after init
}
throw e;
} Prevention
- Configure the Draco decoder URL at app startup, before loading any compressed assets
- Always await decoder initialization before issuing decode requests
- Verify decoder URL reachability and CSP/CORS allowances in CI
- Never post raw worker messages manually; use the DracoCompression API which orders init/decode correctly
When it happens
Trigger: Posting a {type:"decodeMesh"} message to the Draco worker before posting the {type:"init"} message, or after init failed silently; also calling DracoCompressionWorker decode paths when the decoder configuration promise never resolved.
Common situations: Draco decoder URL misconfigured or blocked (CDN offline, CSP), CustomEXTRA headers/CORS preventing the WASM/JS module load, calling mesh conversion before `dracoCompression.Configuration` with `decoder.available` true, or racing multiple workers where the decode lands in a not-yet-initialized worker.
Related errors
- Draco codec module is not available
- Draco: Encoder module is not available.
- Draco: Decoder module is not available
- Recast is not initialized. Please call InitRecast first.
- Unable to generate navMesh/tileCache: ${e}
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/ee9c4835a394e2c2.
Report an issue: GitHub.