{"record":{"id":"5d5f93db48368ef1","repo":"BabylonJS/Babylon.js","slug":"draco-encoder-module-is-not-available","errorCode":null,"errorMessage":"Draco: Encoder module is not available.","messagePattern":"Draco: Encoder module is not available\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Meshes/Compression/dracoCompressionWorker.ts","lineNumber":159,"sourceCode":"export function EncoderWorkerFunction(): void {\r\n    let encoderPromise: Promise<EncoderModule> | undefined;\r\n\r\n    onmessage = (event) => {\r\n        const message = event.data;\r\n        switch (message.id) {\r\n            case \"init\": {\r\n                // if URL is provided then load the script. Otherwise expect the script to be loaded already\r\n                if (message.url) {\r\n                    importScripts(message.url);\r\n                }\r\n                const initEncoderObject = message.wasmBinary ? { wasmBinary: message.wasmBinary } : {};\r\n                encoderPromise = DracoEncoderModule(initEncoderObject);\r\n                postMessage({ id: \"initDone\" });\r\n                break;\r\n            }\r\n            case \"encodeMesh\": {\r\n                if (!encoderPromise) {\r\n                    throw new Error(\"Draco: Encoder module is not available.\");\r\n                }\r\n                encoderPromise\r\n                    // eslint-disable-next-line github/no-then\r\n                    .then((encoder) => {\r\n                        const result = EncodeMesh(encoder, message.attributes, message.indices, message.options);\r\n                        postMessage({ id: \"encodeMeshSuccess\", encodedMeshData: result }, result ? [result.data.buffer] : undefined);\r\n                    })\r\n                    // eslint-disable-next-line github/no-then\r\n                    .catch((error) => {\r\n                        postMessage({ id: \"encodeMeshError\", errorMessage: error.message });\r\n                    });\r\n                break;\r\n            }\r\n        }\r\n    };\r\n}\r\n\r\n/**\r","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Meshes/Compression/dracoCompressionWorker.ts#L141-L177","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Always send the 'init' message with the Draco encoder module/URL first and wait for the 'initDone' reply before sending 'encodeMesh'.","Queue encodeMesh requests until initDone is received rather than posting them immediately.","If init failed, re-create the worker and retry the init handshake instead of reusing the stale worker."],"exampleFix":"// before\nworker.postMessage({ id: 'encodeMesh', attributes, indices }); // init not sent\n\n// after\nworker.onmessage = (m) => {\n  if (m.data.id === 'initDone') worker.postMessage({ id: 'encodeMesh', attributes, indices, options });\n};\nworker.postMessage({ id: 'init', moduleConfig });","handlingStrategy":"retry","validationCode":"if (!encoderWorkerReady) {\n  throw new Error('encoder worker not initialized: wait for initDone before encodeMesh');\n}","typeGuard":"const isWorkerReady = (w: { ready: boolean }): w is { ready: true } => w.ready === true;","tryCatchPattern":"try {\n  return await sendEncodeRequest(message);\n} catch (e) {\n  if (String(e?.message).includes('Encoder module is not available')) {\n    await initEncoderWorker(); // resend 'init', await 'initDone'\n    return await sendEncodeRequest(message);\n  }\n  throw e;\n}","preventionTips":["Gate encodeMesh sends behind the worker's 'initDone' postMessage.","Queue or buffer encode requests issued before init completes.","Treat a failed init as fatal for the worker: recreate it rather than reusing.","Add an integration test covering the init -> encode handshake ordering."],"tags":["draco","worker","initialization-order","async"],"backgroundTag":"module-not-initialized","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}