remix-run/react-router · error · Error
The React Router Vite plugin requires the use of a Vite…
Error message
The React Router Vite plugin requires the use of a Vite config file
What it means
For Framework Mode builds, the React Router plugin spawns a child compiler (for SSR/client variants) and re-loads the same Vite config file so parent and child plugin instances keep independent state. If `viteConfig.configFile` is falsy, there is no file to reload, so the plugin throws. An inline or disabled config file cannot be duplicated safely and would risk shared mutable plugin state between compilers.
Solutions
- Create a real vite.config.ts (or .js/.mjs) at the project root containing the `reactRouter()` plugin and build without `--configFile false`
- If using a non-default filename, pass it explicitly: `react-router build --config vite.config.rr.ts` so `configFile` resolves to a value
- For programmatic builds, write the inline config to a temporary file and point `configFile` at it rather than disabling config files
Example fix
# before vite build --configFile false # after react-router build # vite.config.ts with reactRouter() plugin is auto-discovered
Defensive patterns
Strategy: validation
Validate before calling
// Before invoking programmatic builds, confirm a config file exists
import fs from 'node:fs';
if (!['vite.config.ts', 'vite.config.js', 'vite.config.mts', 'vite.config.mjs'].some((f) => fs.existsSync(path.join(root, f)))) {
throw new Error('A vite.config.* file is required for React Router builds');
} Type guard
const configFilePathExists = (root: string): boolean =>
['ts', 'mts', 'js', 'mjs'].some((ext) =>
fs.existsSync(path.join(root, `vite.config.${ext}`)),
); Try / catch
try {
await build({ configFile: false });
} catch (e) {
if (e instanceof Error && e.message.includes('requires the use of a Vite config file')) {
// write inline config to a temp file and rebuild with configFile set to it
} else throw e;
} Prevention
- Always keep a real vite.config.ts in React Router Framework Mode projects
- Never pass `--configFile false` to react-router/vite builds
- For programmatic configs, write them to a file and reference via `configFile`
When it happens
Trigger: Running a build with `--configFile false` (or `configFile: false` passed programmatically); calling `vite.build({ configFile: false, plugins: [reactRouter()] })` with an entirely inline config; setting `configFile` to a path Vite fails to resolve so the resolved config's `configFile` ends up null.
Common situations: Programmatic builds in monorepo tooling that construct Vite configs inline; scripts copied from plain Vite projects that disable config discovery; moving the config to a non-default filename without pointing `--config` at it.
Related errors
- Custom Vite manifest paths are not supported
- React Router Vite plugin not found in Vite config
- Could not find a root route module in the app directory as
- Error loading
- Prerender: Failed to start Vite preview server
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/29ccba274cce8b54.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/plugin.ts:1429
};
}
},
async configResolved(resolvedViteConfig) {
await initEsModuleLexer;
viteConfig = resolvedViteConfig;
invariant(viteConfig);
// We load the same Vite config file again for the child compiler so
// that both parent and child compiler's plugins have independent state.
// If we re-used the `viteUserConfig.plugins` array for the child
// compiler, it could lead to mutating shared state between plugin
// instances in unexpected ways, e.g. during `vite build` the
// `configResolved` plugin hook would be called with `command = "build"`
// by parent and then `command = "serve"` by child, which some plugins
// may respond to by updating state referenced by the parent.
if (!viteConfig.configFile) {
throw new Error(
"The React Router Vite plugin requires the use of a Vite config file",
);
}
let vite = getVite();
let childCompilerConfigFile = await vite.loadConfigFromFile(
{
command: viteConfig.command,
mode: viteConfig.mode,
},
viteConfig.configFile,
);
invariant(
childCompilerConfigFile,
"Vite config file was unable to be resolved for React Router child compiler",
);View on GitHub (pinned to 6beaca3952)