{"record":{"id":"c92164f789294d7a","repo":"remix-run/react-router","slug":"could-not-find-a-root-route-module-in-the-app-dire","errorCode":null,"errorMessage":"Could not find a root route module in the app directory: ${appDirectory}","messagePattern":"Could not find a root route module in the app directory: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-fs-routes/flatRoutes.ts","lineNumber":87,"sourceCode":"\n    return values;\n  }\n}\n\nexport function flatRoutes(\n  appDirectory: string,\n  ignoredFilePatterns: string[] = [],\n  prefix = \"routes\",\n) {\n  let ignoredFileRegex = Array.from(new Set([\"**/.*\", ...ignoredFilePatterns]))\n    .map((re) => makeRe(re))\n    .filter((re: any): re is RegExp => !!re);\n  let routesDir = path.join(appDirectory, prefix);\n\n  let rootRoute = findFile(appDirectory, \"root\", routeModuleExts);\n\n  if (!rootRoute) {\n    throw new Error(\n      `Could not find a root route module in the app directory: ${appDirectory}`,\n    );\n  }\n\n  if (!fs.existsSync(routesDir)) {\n    throw new Error(\n      `Could not find the routes directory: ${routesDir}. Did you forget to create it?`,\n    );\n  }\n\n  // Only read the routes directory\n  let entries = fs.readdirSync(routesDir, {\n    withFileTypes: true,\n    encoding: \"utf-8\",\n  });\n\n  let routes: string[] = [];\n  for (let entry of entries) {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-fs-routes/flatRoutes.ts#L69-L105","documentation":"flatRoutes() from @react-router/fs-routes derives the route tree from the filesystem and requires a root route module (root.tsx / root.jsx / root.mdx / etc., matched by routeModuleExts) directly inside the app directory. It looks the root file up before ever scanning routes/ and throws immediately when no match is found, since without a root the route tree has no top-level route to hang entries off.","triggerScenarios":"Calling flatRoutes() when appDirectory (default 'app') contains no file named root with any of the supported route module extensions — e.g. the root was renamed, lives in a subdirectory, or appDirectory was customized to a folder without it.","commonSituations":"Setting appDirectory: \"src\" while root.tsx still lives in \"src/app\"; renaming root.tsx to app.tsx; starting a project from a template that omits the root module.","solutions":["Create app/root.tsx exporting a default root component (and usually a Layout export)","Point the appDirectory config at the directory that actually contains your root module","If you renamed the root on purpose, rename it back — flatRoutes hard-requires the name 'root'"],"exampleFix":"// before — react-router.config.ts (root.tsx actually lives in src/app/)\nexport default { appDirectory: \"src\" };\n\n// after\nexport default { appDirectory: \"src/app\" };\n// or simply create src/root.tsx","handlingStrategy":"validation","validationCode":"import fs from \"node:fs\";\nimport path from \"node:path\";\nconst appDirectory = \"app\"; // same value passed to flatRoutes / config\nconst exts = [\".tsx\", \".ts\", \".jsx\", \".js\", \".mjs\", \".mdx\"];\nconst hasRoot = exts.some((e) => fs.existsSync(path.join(appDirectory, `root${e}`)));\nif (!hasRoot) throw new Error(`Missing root route module in ${appDirectory}`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the root module named root.* directly inside appDirectory","When changing appDirectory, verify root.* exists there before running the dev server","Include the root file in project templates and scaffolds"],"tags":["file-routing","fs-routes","root-route","config"],"backgroundTag":"missing-root-route","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}