BabylonJS/Babylon.js · error · Error

Draco codec module is not available

Error message

Draco codec module is not available

What it means

The DracoCodec constructor checks whether the Draco decoder WASM module is already available in scope. If it is not, and no jsModule override was supplied in the configuration, and no CDN URL is configured to load the module from, the codec cannot ever be initialized and it throws this Error. Draco compression support requires the external draco_decoder WASM script to be present or loadable.

Source

Thrown at packages/dev/core/src/Meshes/Compression/dracoCodec.ts:145

        if (useWorkers) {
            // eslint-disable-next-line github/no-then
            this._workerPoolPromise = codecInfo.wasmBinaryPromise.then((wasmBinary) => {
                const workerContent = this._getWorkerContent();
                const workerBlobUrl = URL.createObjectURL(new Blob([workerContent], { type: "application/javascript" }));

                // eslint-disable-next-line @typescript-eslint/promise-function-async
                return new AutoReleaseWorkerPool(numberOfWorkers, () => {
                    const worker = new Worker(workerBlobUrl);
                    return initializeWebWorker(worker, wasmBinary, codecInfo.url);
                });
            });
        } else {
            // eslint-disable-next-line github/no-then
            this._modulePromise = codecInfo.wasmBinaryPromise.then(async (wasmBinary) => {
                if (!this._isModuleAvailable()) {
                    if (!configuration.jsModule) {
                        if (!codecInfo.url) {
                            throw new Error("Draco codec module is not available");
                        }
                        await Tools.LoadBabylonScriptAsync(codecInfo.url);
                    }
                }
                return await this._createModuleAsync(wasmBinary as ArrayBuffer, configuration.jsModule);
            });
        }
    }

    /**
     * Returns a promise that resolves when ready. Call this manually to ensure the draco codec is ready before use.
     * @returns a promise that resolves when ready
     */
    public async whenReadyAsync(): Promise<void> {
        if (this._workerPoolPromise) {
            await this._workerPoolPromise;
            return;
        }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Load the Draco decoder script first: await Tools.LoadBabylonScriptAsync('https://preview.babylonjs.com/draco_decoder.js') (or include the <script> tag) before creating the codec.
  2. Set configuration.jsModule to an already-imported Draco decoder module to bypass script loading.
  3. Set a valid codecInfo.url / configuration so the loader can fetch the decoder, and ensure the URL is reachable from your environment.
  4. Ensure wasmBinary / decoder files are served locally and DracoCompression.URLPrefix points at them for offline apps.

Example fix

// before
const codec = await DracoCodec.GetAsync(); // throws: module never loaded, no url

// after
import DracoDecoderModule from 'draco3dgltf';
const codec = await DracoCodec.GetAsync({ jsModule: DracoDecoderModule });
Defensive patterns

Strategy: fallback

Validate before calling

// ensure the Draco decoder module is loadable before using Draco compression
if (typeof DracoDecoderModule === 'undefined' && !dracoConfig?.jsModule && !dracoConfig?.url) {
  throw new Error('Draco decoder unavailable: provide configuration.jsModule or a reachable url');
}

Type guard

const isDracoReady = (cfg: unknown): cfg is { jsModule: Function } =>
  !!cfg && typeof (cfg as any).jsModule === 'function';

Try / catch

try {
  geometry = await DracoCompression.DecodeMeshToGeometryAsync(name, scene, meshData);
} catch (e) {
  if (String(e?.message).includes('Draco codec module is not available')) {
    await Tools.LoadBabylonScriptAsync('https://cdn.babylonjs.com/draco_decoder.js');
    geometry = await DracoCompression.DecodeMeshToGeometryAsync(name, scene, meshData);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Using DracoCompression / loading a .draco or glTF with Draco extension when the Draco decoder script was never loaded, configuration.jsModule is not provided, and codecInfo.url is falsy (no CDN/default URL configured and Tools.LoadBabylonScriptAsync cannot be attempted).

Common situations: Bundling apps with tree-shaking that strips the side-effect script load; offline/air-gapped environments where the default CDN is unreachable and no local URL is given; custom build pipelines that exclude babylonjs-draco decoder scripts; misconfigured DracoCompressionConfiguration.

Related errors


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