remix-run/react-router · error

The `routeDiscovery.mode` config cannot be set to "lazy" whe

Error message

The `routeDiscovery.mode` config cannot be set to "lazy" when setting `ssr:false`

What it means

`routeDiscovery.mode: "lazy"` relies on a server-side manifest endpoint (`/__manifest`) that only exists when SSR is enabled. With `ssr: false` (SPA mode) there is no server to serve the manifest, so this combination is rejected; SPA mode must use `routeDiscovery.mode: "initial"` (which is the default when `ssr: false`).

Source

Thrown at packages/react-router-dev/config/config.ts:599

      );
    }
  }

  let routeDiscovery: ResolvedReactRouterConfig["routeDiscovery"];
  if (userRouteDiscovery == null) {
    if (ssr) {
      routeDiscovery = {
        mode: "lazy",
        manifestPath: "/__manifest",
      };
    } else {
      routeDiscovery = { mode: "initial" };
    }
  } else if (userRouteDiscovery.mode === "initial") {
    routeDiscovery = userRouteDiscovery;
  } else if (userRouteDiscovery.mode === "lazy") {
    if (!ssr) {
      return err(
        'The `routeDiscovery.mode` config cannot be set to "lazy" when setting `ssr:false`',
      );
    }

    let { manifestPath } = userRouteDiscovery;
    if (manifestPath != null && !manifestPath.startsWith("/")) {
      return err(
        "The `routeDiscovery.manifestPath` config must be a root-relative " +
          'pathname beginning with a slash (i.e., "/__manifest")',
      );
    }

    routeDiscovery = userRouteDiscovery;
  }

  let appDirectory = Path.resolve(root, userAppDirectory || "app");
  let buildDirectory = Path.resolve(root, userBuildDirectory);

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Remove the `routeDiscovery` block entirely — with `ssr: false` it defaults to `initial`, which is what SPAs need.
  2. Or set it explicitly: `routeDiscovery: { mode: "initial" }`.
  3. If you intended SSR, restore `ssr: true` and keep `mode: "lazy"`.
  4. Re-run the build to confirm config validation passes.

Example fix

// before
export default {
  ssr: false,
  routeDiscovery: { mode: "lazy", manifestPath: "/__manifest" },
};

// after
export default {
  ssr: false,
  routeDiscovery: { mode: "initial" },
};
Defensive patterns

Strategy: validation

Validate before calling

const cfg = { ssr: false } as ReactRouterConfig;
if (cfg.ssr === false && cfg.routeDiscovery?.mode === "lazy") {
  throw new Error("SPA mode requires routeDiscovery.mode 'initial'");
}

Prevention

When it happens

Trigger: A config containing both `ssr: false` and `routeDiscovery: { mode: "lazy" }` — typically left over from an SSR setup being converted to SPA mode, where only the `ssr` flag was flipped.

Common situations: Converting an SSR app to an SPA by setting `ssr: false` without adjusting route discovery; copying a config between projects with different SSR settings; explicit opt-in to lazy discovery during a migration to `ssr: false` for static hosting.

Related errors


AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18). Data as JSON: /api/errors/c2a20f09088d8a26. Report an issue: GitHub.