remix-run/react-router · error · Error
Could not resolve module ID for ${url}
Error message
Could not resolve module ID for ${url} What it means
Thrown inside the child compiler's route-transform pipeline (`getRouteModuleExports`-style flow). React Router resolves each route file to a URL, calls `pluginContainer.resolveId(url, undefined, { ssr: true })`, and requires a non-null result. A null result means no plugin in the child Vite container recognizes the file as a loadable module, so React Router cannot transform it or read its exports.
Source
Thrown at packages/react-router-dev/vite/plugin.ts:542
): Promise<string> => {
if (!viteChildCompiler) {
throw new Error("Vite child compiler not found");
}
// We transform the route module code with the Vite child compiler so that we
// can parse the exports from non-JS files like MDX. This ensures that we can
// understand the exports from anything that Vite can compile to JS, not just
// the route file formats that the Remix compiler historically supported.
let ssr = true;
let { pluginContainer, moduleGraph } = viteChildCompiler;
let routePath = path.resolve(ctx.reactRouterConfig.appDirectory, routeFile);
let url = resolveFileUrl(ctx, routePath);
let resolveId = async () => {
let result = await pluginContainer.resolveId(url, undefined, { ssr });
if (!result) throw new Error(`Could not resolve module ID for ${url}`);
return result.id;
};
let [id, code] = await Promise.all([
resolveId(),
readRouteFile?.() ?? readFile(routePath, "utf-8"),
// pluginContainer.transform(...) fails if we don't do this first:
moduleGraph.ensureEntryFromUrl(url, ssr),
]);
let transformed = await pluginContainer.transform(code, id, { ssr });
return transformed.code;
};
const getRouteModuleExports = async (
viteChildCompiler: Vite.ViteDevServer | null,
ctx: ReactRouterPluginContext,
routeFile: string,View on GitHub (pinned to 1fd704a7da)
Solutions
- Verify the route file exists at the printed absolute path with `ls <routePath>`.
- Confirm the file extension is supported by a plugin in the Vite config (e.g. add `mdx()` for `.mdx`).
- Check `appDirectory` in your config matches where `routes.ts`/route files live.
- For custom extensions, add a Vite plugin that handles `resolveId`/`load` for that extension.
- Reproduce the resolved URL and run it through `vite.resolveId` in a REPL to see which plugin rejects it.
Example fix
// before: routes.ts references a non-existent file
route("/about", "./about-us.tsx");
// after
route("/about", "./about.tsx"); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from "node:fs";
import path from "node:path";
const assertRouteFileExists = (appDir: string, file: string) => {
const abs = path.resolve(appDir, file);
if (!existsSync(abs)) throw new Error(`Route file missing: ${abs}`);
};
// iterate your routes.ts entries and call this for each Type guard
const isResolvable = (ext: string, supported: string[]): boolean => supported.includes(ext);
Prevention
- Keep route files inside the configured `appDirectory`.
- Add Vite plugins for non-JS extensions (`.mdx`, `.vue`) before referencing them in routes.
- Validate route file existence in a pre-build script when using manual `routes.ts`.
When it happens
Trigger: Route file path does not exist on disk (typo in `routes.ts` or a `flatRoutes()` glob mismatch); the file extension is not handled by any Vite plugin (e.g. `.mdx` without `@mdx-js/rollup` registered); the route sits outside `appDirectory`; an alias used in the route path is not resolvable; the file is git-LFS'd or unreadable.
Common situations: Renaming a route file but forgetting to update a manual `route()` entry in `routes.ts`; adding `.mdx` routes before installing the MDX plugin; symlinking routes from outside the app directory; case-sensitivity mismatches between macOS (case-insensitive) and Linux CI.
Related errors
- Unable to define routes with duplicate route id: "${id}"
- The React Router Vite plugin requires the use of a Vite conf
- The "@mdx-js/rollup" plugin should be placed before the Reac
- You tried to define routes asynchronously but started defini
- React Router presets must have a `name` property defined.
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/10b8b8088cc8db26.
Report an issue: GitHub.