BabylonJS/Babylon.js · error · Error

Draco: Encoder module is not available.

Error message

Draco: Encoder module is not available.

What it means

Inside the encoder worker, an 'encodeMesh' message can only be handled after the 'init' message has created the encoderPromise (the loaded Draco encoder module). If an encodeMesh request arrives before initialization, the worker throws this Error because there is no module to encode with.

Source

Thrown at packages/dev/core/src/Meshes/Compression/dracoCompressionWorker.ts:159

export function EncoderWorkerFunction(): void {
    let encoderPromise: Promise<EncoderModule> | 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 initEncoderObject = message.wasmBinary ? { wasmBinary: message.wasmBinary } : {};
                encoderPromise = DracoEncoderModule(initEncoderObject);
                postMessage({ id: "initDone" });
                break;
            }
            case "encodeMesh": {
                if (!encoderPromise) {
                    throw new Error("Draco: Encoder module is not available.");
                }
                encoderPromise
                    // eslint-disable-next-line github/no-then
                    .then((encoder) => {
                        const result = EncodeMesh(encoder, message.attributes, message.indices, message.options);
                        postMessage({ id: "encodeMeshSuccess", encodedMeshData: result }, result ? [result.data.buffer] : undefined);
                    })
                    // eslint-disable-next-line github/no-then
                    .catch((error) => {
                        postMessage({ id: "encodeMeshError", errorMessage: error.message });
                    });
                break;
            }
        }
    };
}

/**

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Always send the 'init' message with the Draco encoder module/URL first and wait for the 'initDone' reply before sending 'encodeMesh'.
  2. Queue encodeMesh requests until initDone is received rather than posting them immediately.
  3. If init failed, re-create the worker and retry the init handshake instead of reusing the stale worker.

Example fix

// before
worker.postMessage({ id: 'encodeMesh', attributes, indices }); // init not sent

// after
worker.onmessage = (m) => {
  if (m.data.id === 'initDone') worker.postMessage({ id: 'encodeMesh', attributes, indices, options });
};
worker.postMessage({ id: 'init', moduleConfig });
Defensive patterns

Strategy: retry

Validate before calling

if (!encoderWorkerReady) {
  throw new Error('encoder worker not initialized: wait for initDone before encodeMesh');
}

Type guard

const isWorkerReady = (w: { ready: boolean }): w is { ready: true } => w.ready === true;

Try / catch

try {
  return await sendEncodeRequest(message);
} catch (e) {
  if (String(e?.message).includes('Encoder module is not available')) {
    await initEncoderWorker(); // resend 'init', await 'initDone'
    return await sendEncodeRequest(message);
  }
  throw e;
}

Prevention

When it happens

Trigger: Posting an 'encodeMesh' message to the Draco encoder worker without first posting 'init' (or before init completes), e.g. a race where encode is called immediately after worker creation or after a failed init.

Common situations: Custom worker plumbing that skips the init handshake; calling encode before the encoder module (WASM) finished loading on slow networks; reusing a worker whose init message failed silently.

Related errors


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