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
- Remove the `routeDiscovery` block entirely — with `ssr: false` it defaults to `initial`, which is what SPAs need.
- Or set it explicitly: `routeDiscovery: { mode: "initial" }`.
- If you intended SSR, restore `ssr: true` and keep `mode: "lazy"`.
- 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 flipping ssr to false, delete the whole routeDiscovery block (the default is correct for SPA).
- Keep a single source of truth for 'is this app SSR or SPA' and derive both flags from it.
- Remember lazy discovery needs the SSR runtime's /__manifest endpoint — no server, no lazy.
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
- The "serverBundles" function must only return strings contai
- The `prerender`/`prerender.paths` config must be a boolean,
- The `prerender.concurrency` config must be a positive intege
- The `routeDiscovery.manifestPath` config must be a root-rela
- Route config in "${routeConfigFile}" is invalid.
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/c2a20f09088d8a26.
Report an issue: GitHub.