remix-run/react-router · error

Route config in "${routeConfigFile}" is invalid.

Error message

Route config in "${routeConfigFile}" is invalid.

What it means

Importing or validating `routes.ts` threw: either the Vite-runner import failed (syntax error, unresolvable import, top-level throw) or `validateRouteConfig` rejected the shape. When Vite supplies `error.loc`/`error.frame`, the message includes a `file:line:column` pointer and the annotated code frame, so the exact spot in the route config is shown beneath the header.

Source

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

      });

      if (!result.valid) {
        return err(result.message);
      }

      // Nest the route config under the resolved root route
      routeConfig = [
        {
          id: "root",
          path: "",
          file: Path.relative(appDirectory, rootRouteFile),
          children: result.routeConfig,
        },
      ];

      routes = configRoutesToRouteManifest(appDirectory, routeConfig);
    } catch (error: any) {
      return err(
        [
          colors.red(`Route config in "${routeConfigFile}" is invalid.`),
          "",
          error.loc?.file && error.loc?.column && error.frame
            ? [
                Path.relative(appDirectory, error.loc.file) +
                  ":" +
                  error.loc.line +
                  ":" +
                  error.loc.column,
                error.frame.trim?.(),
              ]
            : error.stack,
        ]
          .flat()
          .join("\n"),
      );
    }

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Read the `file:line:column` and frame embedded in the error output — it points at the failing expression in the route config.
  2. Fix the import/path/typo it identifies (missing module, bad file extension, wrong relative path).
  3. Confirm the default export is a flat array of route config entries and `satisfies RouteConfig` typechecks.
  4. Run `pnpm run typecheck` (or `tsc`) to catch type-level mistakes in `routes.ts`.

Example fix

// before: app/routes.ts
import { route } from "@react-router/dev/routes";
export default [
  route("about", "./abuot.tsx"), // typo -> import fails, "Route config ... is invalid"
];

// after
import { route } from "@react-router/dev/routes";
export default [
  route("about", "./about.tsx"),
] satisfies RouteConfig;
Defensive patterns

Strategy: try-catch

Validate before calling

// fail fast on broken route file references before building
import fs from "node:fs";
import path from "node:path";
for (const entry of routeConfigEntries) {
  const file = path.join("app", entry.file);
  if (!fs.existsSync(file)) {
    throw new Error(`Route config references missing file: ${entry.file}`);
  }
}

Type guard

function isRouteConfig(v: unknown): v is RouteConfigEntry[] {
  return Array.isArray(v) && v.every((e) => typeof e?.file === "string");
}

Try / catch

try {
  const routesMod = await import("./app/routes.ts");
  const entries = routesMod.default;
  if (!Array.isArray(entries)) throw new Error("routes.ts default export must be an array");
} catch (e: any) {
  if (e.loc?.file) {
    console.error(`${path.relative(process.cwd(), e.loc.file)}:${e.loc.line}:${e.loc.column}`);
    console.error(e.frame?.trim());
  }
  process.exit(1);
}

Prevention

When it happens

Trigger: A broken import in `app/routes.ts` (module not found); exporting a default that is not a valid `RouteConfig` array (e.g. an object or undefined); a helper like a custom `flatRoutes` call throwing; referencing a route file path that fails resolution inside the config.

Common situations: Renaming/moving route files without updating `routes.ts`; typos in `route("about", "./about.tssx")`; a route config helper that reads the filesystem and throws on unexpected structure; TS features in `routes.ts` not supported by the loader after a Vite upgrade.

Related errors


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