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

  1. Create a real vite.config.ts (or .js/.mjs) at the project root containing the `reactRouter()` plugin and build without `--configFile false`
  2. If using a non-default filename, pass it explicitly: `react-router build --config vite.config.rr.ts` so `configFile` resolves to a value
  3. 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

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


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)