{"record":{"id":"10b8b8088cc8db26","repo":"remix-run/react-router","slug":"could-not-resolve-module-id-for-url","errorCode":null,"errorMessage":"Could not resolve module ID for ${url}","messagePattern":"Could not resolve module ID for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":542,"sourceCode":"): Promise<string> => {\n  if (!viteChildCompiler) {\n    throw new Error(\"Vite child compiler not found\");\n  }\n\n  // We transform the route module code with the Vite child compiler so that we\n  // can parse the exports from non-JS files like MDX. This ensures that we can\n  // understand the exports from anything that Vite can compile to JS, not just\n  // the route file formats that the Remix compiler historically supported.\n\n  let ssr = true;\n  let { pluginContainer, moduleGraph } = viteChildCompiler;\n\n  let routePath = path.resolve(ctx.reactRouterConfig.appDirectory, routeFile);\n  let url = resolveFileUrl(ctx, routePath);\n\n  let resolveId = async () => {\n    let result = await pluginContainer.resolveId(url, undefined, { ssr });\n    if (!result) throw new Error(`Could not resolve module ID for ${url}`);\n    return result.id;\n  };\n\n  let [id, code] = await Promise.all([\n    resolveId(),\n    readRouteFile?.() ?? readFile(routePath, \"utf-8\"),\n    // pluginContainer.transform(...) fails if we don't do this first:\n    moduleGraph.ensureEntryFromUrl(url, ssr),\n  ]);\n\n  let transformed = await pluginContainer.transform(code, id, { ssr });\n  return transformed.code;\n};\n\nconst getRouteModuleExports = async (\n  viteChildCompiler: Vite.ViteDevServer | null,\n  ctx: ReactRouterPluginContext,\n  routeFile: string,","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/plugin.ts#L524-L560","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: routes.ts references a non-existent file\nroute(\"/about\", \"./about-us.tsx\");\n// after\nroute(\"/about\", \"./about.tsx\");","handlingStrategy":"validation","validationCode":"import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nconst assertRouteFileExists = (appDir: string, file: string) => {\n  const abs = path.resolve(appDir, file);\n  if (!existsSync(abs)) throw new Error(`Route file missing: ${abs}`);\n};\n// iterate your routes.ts entries and call this for each","typeGuard":"const isResolvable = (ext: string, supported: string[]): boolean =>\n  supported.includes(ext);","tryCatchPattern":null,"preventionTips":["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`."],"tags":["routes","resolve-id","child-compiler","mdx","config"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}