BabylonJS/Babylon.js · error · Error
Unable to generateSoloNavMesh: ${result.error}
Error message
Unable to generateSoloNavMesh: ${result.error} What it means
After dispatching to the Recast WASM generator (solo, tiled, or tile cache depending on parameters), GenerateNavMesh() checks result.success and throws if the underlying @recast-navigation generator reported failure (generator.single-thread.ts:59). The message template says "generateSoloNavMesh" even for tiled/tile-cache paths, but result.error carries the actual Recast failure reason. This indicates Recast could not build a valid nav mesh from the provided geometry/config — e.g. invalid parameters, geometry outside the tile/bounds extents, or an internal Recast error.
Source
Thrown at packages/dev/addons/src/navigation/generator/generator.single-thread.ts:59
const tileSize = parameters.tileSize ?? 0;
const needsTileCache = (parameters.maxObstacles ?? 0) > 0;
const needsTiledNavMesh = tileSize > 0;
if (needsTileCache) {
if (tileSize < 32 || tileSize > 64) {
Logger.Warn("NavigationPlugin: Tile cache is enabled. Recommended tileSize is 32 to 64. Other values may lead to unexpected behavior.");
}
}
// Create the appropriate configuration based on the parameters
const config = needsTileCache ? CreateTileCacheNavMeshConfig(parameters) : needsTiledNavMesh ? CreateTiledNavMeshConfig(parameters) : CreateSoloNavMeshConfig(parameters);
const result = needsTileCache
? recast.generateTileCache(positions, indices, config as TileCacheGeneratorConfig, parameters.keepIntermediates)
: needsTiledNavMesh
? recast.generateTiledNavMesh(positions, indices, config as TiledNavMeshGeneratorConfig, parameters.keepIntermediates)
: recast.generateSoloNavMesh(positions, indices, config as SoloNavMeshGeneratorConfig, parameters.keepIntermediates);
if (!result.success) {
throw new Error(`Unable to generateSoloNavMesh: ${result.error}`);
}
return {
navMesh: result.navMesh,
intermediates: result.intermediates,
navMeshQuery: new recast.NavMeshQuery(result.navMesh),
tileCache: "tileCache" in result ? result.tileCache : undefined,
};
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Read result.error in the message for the actual Recast cause and fix that specific issue first
- Check triangle winding: if the nav mesh comes out empty, set doNotReverseIndices: true (or remove it) in INavMeshParametersV2 to match your mesh winding
- Keep tileSize in the recommended 32–64 range when using tile cache (maxObstacles > 0), as warned at generator.single-thread.ts:46
- Validate your config scale: cellSize/cellHeight/agentRadius/agentHeight/agentMaxClimb and the bounds must match your scene units
- Simplify: try generating a solo nav mesh (no tileSize, no maxObstacles) on a single simple mesh to isolate whether the issue is config or geometry
Example fix
// before
plugin.createNavMesh(meshes, {
tileSize: 128, // outside recommended range for tile cache
maxObstacles: 10,
doNotReverseIndices: true, // wrong for this winding
});
// after
plugin.createNavMesh(meshes, {
tileSize: 64, // within recommended 32-64
maxObstacles: 10,
doNotReverseIndices: false, // correct winding for the source meshes
}); Defensive patterns
Strategy: validation
Validate before calling
function validateNavMeshParameters(p: INavMeshParametersV2) {
const tileSize = p.tileSize ?? 0;
if ((p.maxObstacles ?? 0) > 0 && (tileSize < 32 || tileSize > 64)) {
throw new Error("tileSize must be 32-64 when maxObstacles > 0");
}
if (!p.cellSize || p.cellSize <= 0 || !p.agentRadius || p.agentRadius <= 0) {
throw new Error("Invalid nav mesh config: cellSize/agentRadius must be positive");
}
} Type guard
function isGenerationSuccess(r: { success: boolean; error?: string }): r is { success: true; error?: never } {
return r.success === true;
} Try / catch
try {
const { navMesh, navMeshQuery } = GenerateNavMesh(meshes, parameters);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Unable to generateSoloNavMesh")) {
console.error("Recast failed:", e.message);
// retry with corrected winding: parameters.doNotReverseIndices = !parameters.doNotReverseIndices
}
} Prevention
- Match doNotReverseIndices to your meshes' actual triangle winding; flip it if generation fails or the mesh comes out empty
- Keep tileSize within 32-64 when using tile cache (maxObstacles > 0)
- Tune cellSize/cellHeight/agent* values to your scene's units; avoid copying configs between differently scaled projects
- Test with a simple solo nav mesh on one mesh to isolate config vs geometry issues
- Read result.error from the thrown message — it names the specific Recast failure
When it happens
Trigger: parameters.tileSize > 0 with geometry extents incompatible with the tile config; maxObstacles > 0 with tileSize outside the recommended 32–64 range; SoloNavMeshGeneratorConfig values (cellSize, agentRadius, agentHeight, agentMaxClimb, bounds) too large/small or misaligned for the scene scale; geometry with degenerate/inverted triangles; doNotReverseIndices set wrong so triangles have incorrect winding and Recast culls them all; Recast internal errors reported via result.error.
Common situations: Scene scaled very differently from Recast defaults (tiny or huge units) making cellSize/agent values nonsensical; wrong triangle winding after exporting from a DCC tool without the doNotReverseIndices flag; tileSize/maxObstacles combinations warned about at line 46 but not fatal until generation; copying config from another project whose scene scale differs.
Related errors
- Recast is not initialized. Please call InitRecast first.
- Unable to deserialize NavMesh.
- At least one mesh is needed to create the nav mesh.
- Unable to get nav mesh. No vertices or indices.
- At least one mesh is needed to create the nav mesh.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/688fad56072f618b.
Report an issue: GitHub.