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
- Use the supported single-threaded path instead: create the plugin with CreateNavigationPluginAsync() and call createNavMeshAsync — worker-based generation is documented as not yet supported.
- 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.
- 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).
- Ensure @recast-navigation wasm files are correctly served/bundled so the blob worker can initialize recast before generating.
- 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
- Prefer CreateNavigationPluginAsync (single-threaded) — worker generation is documented as not yet supported.
- Always await createNavMeshAsync and handle rejection instead of relying on the worker callback.
- Validate meshes have non-empty geometry and sane INavMeshParametersV2 (cellSize, tileSize, agent radius) before generating.
- Ensure wasm assets for @recast-navigation are served and reachable from blob workers.
- Inspect raw worker messages during development to catch empty payloads early.
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
- Unable to generate navMesh: ${e}
- Recast is not initialized. Please call InitRecast first.
- At least one mesh is needed to create the nav mesh.
- Unable to get nav mesh. No vertices or indices.
- Unable to generateSoloNavMesh: ${result.error}
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/c932c17a9d91a0a0.
Report an issue: GitHub.