BabylonJS/Babylon.js · error · Error
Unable to get nav mesh. No vertices or indices.
Error message
Unable to get nav mesh. No vertices or indices.
What it means
GenerateNavMesh() extracts vertex positions and triangle indices from the supplied meshes via GetPositionsAndIndices() (generator.single-thread.ts:32). If either extraction returns empty/null, there is no usable geometry to feed Recast, so the library throws. Unlike error 10 this means meshes WERE passed, but their geometry could not be read.
Source
Thrown at packages/dev/addons/src/navigation/generator/generator.single-thread.ts:32
* @param parameters The parameters used to configure the NavMesh generation.
* @returns An object containing the NavMesh and NavMeshQuery.
* @remarks This function generates a NavMesh based on the provided meshes and parameters.
* It supports different configurations such as solo, tiled, and tile cache nav meshes.
* If you need obstacles, ensure that `maxObstacles` is set to a value greater than 0.
* Recommended values for `tileSize` are between 32 and 64 when using obstacles/tile cache.
* If you need a tiled nav mesh, ensure that `tileSize` is set to a value greater than 0.
* @throws Error if the NavMesh data is invalid or cannot be deserialized.
*/
export function GenerateNavMesh(meshes: Array<Mesh>, parameters: INavMeshParametersV2) {
const recast = GetRecast();
if (meshes.length === 0) {
throw new Error("At least one mesh is needed to create the nav mesh.");
}
const [positions, indices] = GetPositionsAndIndices(meshes, { doNotReverseIndices: parameters.doNotReverseIndices });
if (!positions || !indices) {
throw new Error("Unable to get nav mesh. No vertices or indices.");
}
// Decide on the type of nav mesh to generate based on parameters
// If tileSize is set, we will generate a tiled nav mesh
// If maxObstacles is set, we will generate a tile cache nav mesh
// Otherwise, we will generate a solo nav mesh
// Note: tileSize is only used for tiled nav meshes, not tile cache nav meshes
// If both tileSize and maxObstacles are set, we will generate a tile cache
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 parametersView on GitHub (pinned to 0592b347b8)
Solutions
- Ensure meshes are fully loaded/built before generating: await scene.whenReadyAsync() or await the mesh import promise before createNavMesh
- Verify each mesh has geometry: check m.geometry && m.getTotalVertices() > 0 && m.getIndices().length > 0
- Remove empty/placeholder meshes from the array instead of passing them; pass only meshes with real vertex data
- If the mesh is procedurally built, call bakeCurrentTransformIntoVertices / apply vertex data before nav mesh generation
Example fix
// before
const mesh = new Mesh("ground", scene);
plugin.createNavMesh([mesh], parameters); // no vertex data -> throws
// after
const mesh = await CreateGroundAsync("ground", { width: 10, height: 10 }, scene);
await scene.whenReadyAsync();
if (!mesh.geometry || mesh.getTotalVertices() === 0) {
throw new Error("Ground mesh has no geometry");
}
plugin.createNavMesh([mesh], parameters); Defensive patterns
Strategy: validation
Validate before calling
const valid = meshes.filter(m => m.geometry && m.getTotalVertices() > 0 && m.getIndices().length > 0);
if (valid.length === 0) {
throw new Error("No meshes with vertex/index data for nav mesh");
}
GenerateNavMesh(valid, parameters); Type guard
function hasGeometry(mesh: Mesh): boolean {
return !!mesh.geometry && mesh.getTotalVertices() > 0 && mesh.getIndices().length > 0;
} Try / catch
try {
GenerateNavMesh(meshes, parameters);
} catch (e) {
if (e instanceof Error && e.message.includes("No vertices or indices")) {
// await scene.whenReadyAsync(); rebuild/proceduralize meshes; retry
}
} Prevention
- Call createNavMesh only after all mesh imports/loads resolve (await scene.whenReadyAsync())
- Assert each mesh has geometry and >0 vertices/indices before adding it to the list
- Avoid passing placeholder/empty Mesh instances or meshes whose geometry was disposed
- For procedurally built meshes, apply vertex data before generation
When it happens
Trigger: Passing meshes with no geometry data: meshes whose geometry has not finished loading/being built, meshes without vertex data (e.g. only transform nodes or empty Mesh instances), meshes with vertices but zero indices, or meshes whose vertex data was disposed; also doNotReverseIndices edge cases where winding extraction yields nothing.
Common situations: Calling createNavMesh before loadMesh/async import completes; passing Mesh instances created but never built (no VertexData assigned); meshes whose geometry.dispose() was called (e.g. after cloning with reuse options); procedurally building meshes and generating the nav mesh before the first updateVerticesData/bake; thin instances where base geometry is empty.
Related errors
- At least one mesh is needed to create the nav mesh.
- Unable to generateSoloNavMesh: ${result.error}
- At least one mesh is needed to create the nav mesh.
- Unable to generate navMesh: ${e}
- Unable to generate navMesh/tileCache: ${e}
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/7f1834c524ff6d9c.
Report an issue: GitHub.