remix-run/react-router · error
React Router config loading requires Vite's __config_loader…
Error message
React Router config loading requires Vite's __config_loader environment to be runnable.
What it means
When React Router loads react-router.config.ts, it boots an inline Vite dev server with a dedicated environment named '__config_loader', created through vite.createRunnableDevEnvironment. After creating the server it asserts vite.isRunnableDevEnvironment(environment); if that returns false — typically because user vite config or a plugin overrode environments.__config_loader.createEnvironment with a non-runnable environment, or the resolved Vite version's environment API doesn't match — config loading cannot execute and the error is thrown after closing the dev server.
Solutions
- Scope custom environments config to 'client' and 'ssr' only and remove any '__config_loader' key
- Align the vite version with the peer range @react-router/dev requires (dedupe vite in the lockfile)
- If a plugin injects environment factories, restrict it so it skips the __config_loader environment
Example fix
// before (vite.config.ts)
export default defineConfig({
environments: {
__config_loader: { createEnvironment: myCustomEnv }, // clobbers React Router's
},
});
// after
export default defineConfig({
environments: {
client: { /* ... */ },
ssr: { /* ... */ }, // leave __config_loader to React Router
},
}); Defensive patterns
Strategy: validation
Validate before calling
import { resolveConfig } from "vite";
const cfg = await resolveConfig({ configFile: "vite.config.ts" }, "serve");
if (cfg.environments && "__config_loader" in cfg.environments) {
throw new Error("Remove custom __config_loader environment config — React Router owns it");
} Prevention
- Scope environments config to 'client' and 'ssr' only
- Pin/dedupe the vite version to the one @react-router/dev peers with
- Re-check environment config after Vite major upgrades
When it happens
Trigger: A vite.config.ts that defines environments.__config_loader (or a plugin hook that injects environment config matching every environment) with a custom non-runnable createEnvironment; a mismatched/duplicated Vite version resolved in the workspace.
Common situations: Adding per-environment config for client/ssr and accidentally covering __config_loader; monorepo/pnpm hoisting pulling a different vite instance than the one @react-router/dev expects; upgrading Vite major versions ahead of React Router support.
Related errors
- When using the React Router `basename` and the Vite `base`…
- Custom Vite manifest paths are not supported
- Error loading
- Failed to load CSS for
- React Router Vite plugin not found in Vite config
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/288d0edf90795db0.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/vite-runner.ts:66
configFile: false,
envDir: false,
plugins: [],
environments: {
__config_loader: {
consumer: "server",
dev: {
createEnvironment: (name, config, context) =>
vite.createRunnableDevEnvironment(name, config),
},
},
},
});
const environment = devServer.environments.__config_loader;
if (!vite.isRunnableDevEnvironment(environment)) {
await devServer.close();
throw new Error(
"React Router config loading requires Vite's __config_loader environment to be runnable.",
);
}
return { devServer, environment, runner: environment.runner };
}
View on GitHub (pinned to 6beaca3952)