remix-run/react-router · error

${reactRouterConfigFile} must provide a default export

Error message

${reactRouterConfigFile} must provide a default export

What it means

The React Router config file was imported through the Vite runner, but its module has no `default` export (`configModule.default === undefined`). React Router requires the config file to export its configuration object as the default export, so config resolution returns this error before any validation runs.

Source

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

  viteRunnerContext: ViteRunner.Context;
  reactRouterConfigFile?: string;
  skipRoutes?: boolean;
  validateConfig?: ValidateConfigFunction;
}): Promise<ConfigResult> {
  let reactRouterUserConfig: ReactRouterConfig = {};

  if (reactRouterConfigFile) {
    try {
      if (!fs.existsSync(reactRouterConfigFile)) {
        return err(`${reactRouterConfigFile} no longer exists`);
      }

      let configModule = await viteRunnerContext.runner.import(
        reactRouterConfigFile,
      );

      if (configModule.default === undefined) {
        return err(`${reactRouterConfigFile} must provide a default export`);
      }

      if (typeof configModule.default !== "object") {
        return err(`${reactRouterConfigFile} must export a config`);
      }

      reactRouterUserConfig = configModule.default;

      if (validateConfig) {
        const error = validateConfig(reactRouterUserConfig);
        if (error) {
          return err(error);
        }
      }
    } catch (error) {
      return err(`Error loading ${reactRouterConfigFile}: ${error}`);
    }
  }

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Add `export default` to the config object in the file named in the error.
  2. If using a named export locally, add `export default config;` at the end of the file.
  3. Verify there is exactly one default export and it is the top-level config object.
  4. Restart the dev server after fixing (config is loaded once per readConfig call).

Example fix

// before: react-router.config.ts
export const config = {
  ssr: true,
};

// after
export default {
  ssr: true,
};
Defensive patterns

Strategy: type-guard

Validate before calling

// quick check before starting the toolchain
import fs from "node:fs";
const src = fs.readFileSync("react-router.config.ts", "utf8");
if (!/^export\s+default\b/m.test(src) && !/^export\s*\{[^}]*\bas\s+default\b/m.test(src)) {
  throw new Error("react-router.config.ts must have a default export");
}

Type guard

function hasDefaultConfig(mod: unknown): mod is { default: object } {
  return (
    typeof mod === "object" &&
    mod !== null &&
    "default" in mod &&
    typeof (mod as { default: unknown }).default === "object"
  );
}

Prevention

When it happens

Trigger: Writing `react-router.config.ts` with only named exports (e.g. `export const config = {...}`), exporting nothing, or exporting only types/side effects; the file loads fine but `mod.default` is undefined.

Common situations: Converting a shared config snippet into named exports and forgetting the `default` keyword; copy-pasting an example that uses `export default` into a file where it gets wrapped or re-exported without default; refactoring tools (codemods) stripping the default export.

Related errors


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