BabylonJS/Babylon.js · error · Error

Unable to generate navMesh/tileCache: ${e}

Error message

Unable to generate navMesh/tileCache: ${e}

What it means

This error is thrown inside the onmessage handler of GenerateNavMeshWithWorker (generator.worker.ts:66) when a message arrives from the navmesh Web Worker that is neither a success:false failure nor carries usable navMesh (or tileCache) binary data. In other words, the worker replied, but its payload contained no deserializable navmesh/tilecache bytes, so the plugin cannot build a NavMesh. It is the 'silent empty response' branch of worker-based navmesh generation in Babylon.js's recast-navigation-js wrapper.

Source

Thrown at packages/dev/addons/src/navigation/generator/generator.worker.ts:66

        } else {
            const { navMesh, tileCache } = e.data;
            if (tileCache) {
                // if tileCache is present, the binary data contains the navmesh and the tilecache as well
                const tileCacheArray = new Uint8Array(tileCache);
                const navMeshData = BuildFromTileCacheData(tileCacheArray, CreateDefaultTileCacheMeshProcess());
                workerOptions.completion(navMeshData.navMesh, navMeshData.navMeshQuery, navMeshData.tileCache);
                return;
            } else {
                if (navMesh) {
                    // deserialize the navmesh only (no tilecache present)
                    const navMeshArray = new Uint8Array(navMesh);
                    const navMeshData = BuildFromNavmeshData(navMeshArray);
                    workerOptions.completion(navMeshData.navMesh, navMeshData.navMeshQuery, undefined);
                    return;
                }
            }

            throw new Error(`Unable to generate navMesh/tileCache: ${e}`);
        }
    };

    // send message to worker
    const [positions, indices] = GetPositionsAndIndices(meshes, { doNotReverseIndices: parameters.doNotReverseIndices });
    const positionsCopy = new Float32Array(positions);
    const indicesCopy = new Uint32Array(indices);
    workerOptions.worker.postMessage({ positions: positionsCopy, indices: indicesCopy, parameters }, [positionsCopy.buffer, indicesCopy.buffer]);
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Use the supported single-threaded path instead: create the plugin with CreateNavigationPluginAsync() and call createNavMeshAsync — worker-based generation is documented as not yet supported.
  2. Log/inspect the raw worker message (e.data) to see what the worker actually returned; check the worker-side generator for errors swallowed before posting.
  3. Verify the meshes passed to createNavMeshAsync have valid, walkable geometry (non-empty vertex/index buffers, correct winding; try doNotReverseIndices) and sensible parameters (cellSize, tileSize, agent radius/height).
  4. Ensure @recast-navigation wasm files are correctly served/bundled so the blob worker can initialize recast before generating.
  5. Wait for the completion callback (the promise from createNavMeshAsync) and guard against generating on an empty or partially loaded scene.

Example fix

// before (worker plugin, experimental)
const plugin = await CreateNavigationPluginWorkerAsync();
await plugin.createNavMeshAsync(meshes, params);

// after (supported single-threaded path)
const plugin = await CreateNavigationPluginAsync();
await plugin.createNavMeshAsync(meshes, params);
Defensive patterns

Strategy: try-catch

Validate before calling

// Before using the worker plugin
if (typeof window === "undefined" || !window.Worker) {
    // fall back to single-threaded factory
}
if (meshes.length === 0 || meshes.every(m => !m.geometry || m.getTotalVertices() === 0)) {
    throw new Error("No geometry provided for navmesh generation");
}

Type guard

function hasNavMeshPayload(data: unknown): data is { navMesh: ArrayBuffer | Uint8Array } {
    return !!data && typeof data === "object" && "navMesh" in data && (data as any).navMesh != null;
}

Try / catch

try {
    const { navMesh } = await plugin.createNavMeshAsync(meshes, params);
} catch (e) {
    if (String(e).includes("Unable to generate navMesh/tileCache")) {
        // worker returned no data: fall back to single-threaded generation
        const plugin2 = await CreateNavigationPluginAsync();
        await plugin2.createNavMeshAsync(meshes, params);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling plugin.createNavMeshAsync on a plugin created via CreateNavigationPluginWorkerAsync when the worker posts a message whose data lacks both a truthy navMesh field and a truthy tileCache field (and is not marked success:false). This happens when generation produced no output — e.g. the worker-side generator threw before serializing, the posted parameters yielded an empty navmesh, or the blob-worker (built from GenerateNavMeshWorker.toString()) failed to load the wasm module and returned an incomplete payload.

Common situations: Using the experimental worker factory (workers are explicitly 'not yet supported' per the file header), generating a navmesh from meshes whose geometry produces zero walkable area (wrong axis/winding, no geometry within the tile bounds), wasm assets not bundled/reachable from the blob worker, or misconfigured INavMeshParametersV2 (tileSize/cellSize) yielding empty tiles.

Related errors


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