BabylonJS/Babylon.js · error · Error

There is no NavMesh generated.

Error message

There is no NavMesh generated.

What it means

RecastJSCrowd's constructor (RecastJSCrowd.ts:112) throws this when the supplied RecastNavigationJSPluginV2 has no navMesh (plugin.navMesh is undefined). The crowd needs an actual recast NavMesh object to construct the underlying @recast-navigation Crowd, so creating a crowd before any navmesh has been generated is impossible. This is an ordering error: crowd creation must follow a successful createNavMesh/createNavMeshAsync.

Source

Thrown at packages/dev/addons/src/navigation/plugin/RecastJSCrowd.ts:112

        /**
         * The destination that the agent reached
         */
        destination: Vector3;
    }>();

    /**
     * Constructor
     * @param plugin recastJS plugin
     * @param maxAgents the maximum agent count in the crowd
     * @param maxAgentRadius the maximum radius an agent can have
     * @param scene to attach the crowd to
     * @returns the crowd you can add agents to
     */
    public constructor(plugin: RecastNavigationJSPluginV2, maxAgents: number, maxAgentRadius: number, scene: Scene) {
        this._navigationPlugin = plugin;

        if (!plugin.navMesh) {
            throw new Error("There is no NavMesh generated.");
        }

        this._recastCrowd = new (GetRecast().Crowd)(plugin.navMesh, {
            maxAgents,
            maxAgentRadius,
        });

        this._scene = scene;
        this._engine = scene.getEngine();

        this._onBeforeAnimationsObserver = scene.onBeforeAnimationsObservable.add(() => {
            this.update(this._engine.getDeltaTime() * 0.001 * plugin.timeFactor);
        });
    }

    /**
     * Add a new agent to the crowd with the specified parameter a corresponding transformNode.
     * You can attach anything to that node. The node position is updated in the scene update tick.

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Generate the navmesh first and await it: await plugin.createNavMeshAsync(meshes, params) (or plugin.createNavMesh(meshes, params)), then construct the crowd.
  2. Check plugin.navMesh is set before creating the crowd; if undefined, the earlier generation failed — fix that first.
  3. If using CreateNavigationPluginWorkerAsync, only use createNavMeshAsync (sync createNavMesh is disabled and logs a warning, never populating navMesh).
  4. Restructure initialization so crowd creation happens in the async continuation after generation resolves, not before.

Example fix

// before
const plugin = await CreateNavigationPluginAsync();
const crowd = new RecastJSCrowd(plugin, 10, 0.5, scene); // throws: no navMesh yet
await plugin.createNavMeshAsync(meshes, params);

// after
const plugin = await CreateNavigationPluginAsync();
await plugin.createNavMeshAsync(meshes, params);
if (!plugin.navMesh) throw new Error("navmesh generation failed");
const crowd = new RecastJSCrowd(plugin, 10, 0.5, scene);
Defensive patterns

Strategy: validation

Validate before calling

// Run BEFORE constructing the crowd
if (!plugin.navMesh) {
    throw new Error("Create a navmesh (await plugin.createNavMeshAsync(...)) before creating a crowd");
}
const crowd = new RecastJSCrowd(plugin, maxAgents, maxAgentRadius, scene);

Type guard

function hasNavMesh(plugin: RecastNavigationJSPluginV2): plugin is RecastNavigationJSPluginV2 & { navMesh: NonNullable<RecastNavigationJSPluginV2["navMesh"]> } {
    return plugin.navMesh != null;
}

Try / catch

let crowd: RecastJSCrowd;
try {
    crowd = new RecastJSCrowd(plugin, 10, 0.5, scene);
} catch (e) {
    if (e instanceof Error && e.message.includes("no NavMesh generated")) {
        // generate navmesh then retry once
        await plugin.createNavMeshAsync(meshes, params);
        crowd = new RecastJSCrowd(plugin, 10, 0.5, scene);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling new RecastJSCrowd(plugin, maxAgents, maxAgentRadius, scene) before plugin.createNavMesh(...) / await plugin.createNavMeshAsync(...) succeeded, after a failed navmesh generation, or on a plugin whose createNavMesh was stubbed (e.g. the worker-mode plugin overrides createNavMesh to return null and never sets navMesh unless createNavMeshAsync completed).

Common situations: Calling createNavMesh without awaiting it (fire-and-forget on a promise), navmesh generation failing silently earlier, instantiating the crowd in scene-construction code that runs before async generation resolves, or using the worker plugin where only the sync createNavMesh was (invalidly) called.

Related errors


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