{"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":"exception","errorClass":"Error","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/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-fs-routes/flatRoutes.ts#L69-L105","documentation":"Thrown by flatRoutes() (createFileRouteMapper) when findFile(appDirectory, 'root', routeModuleExts) returns null — i.e. no root route module (root.tsx/root.jsx/root.ts/…) exists directly in the app directory. The root route is mandatory for file-system routing because it provides the <html> shell and layout.","triggerScenarios":"Calling flatRoutes() (directly or via the fs-routes default export) where the app directory has no file matching `root.{ts,tsx,js,jsx,...}`. Common when appDirectory is misconfigured (points to the wrong folder) or the root file was renamed/deleted.","commonSituations":"Setting `appDirectory` in react-router.config.ts to a custom path that doesn't contain root.tsx. Fresh scaffold where root.tsx wasn't generated. Renaming root.tsx to app.tsx (not a supported convention). Monorepo where the app dir resolves to the package root instead of ./app.","solutions":["Create app/root.tsx (default export a component rendering <html>… with <Outlet/>).","Verify react-router.config.ts `appDirectory` points to the folder that should contain root.tsx.","Run `pnpm react-router typegen` to confirm the route manifest resolves.","Check that the file extension is in the supported routeModuleExts list (ts,tsx,js,jsx,mdx)."],"exampleFix":"// before: app/ has only routes/, no root file → create app/root.tsx\n// app/root.tsx\nimport { Outlet } from 'react-router';\nexport default function Root() {\n  return (<html><body><Outlet/></body></html>);\n}","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport { exts } from './routeModuleExts'; // mimic the supported list: ts,tsx,js,jsx,mdx,...\nfunction hasRootRoute(appDirectory: string): boolean {\n  return ['ts','tsx','js','jsx','mdx'].some((e) => existsSync(`${appDirectory}/root.${e}`));\n}\nif (!hasRootRoute(appDirectory)) throw new Error('Missing app/root.tsx');","typeGuard":"function appDirectoryHasRoot(appDirectory: string, exts: string[]): boolean {\n  const { existsSync } = require('node:fs');\n  return exts.some((e) => existsSync(`${appDirectory}/root.${e}`));\n}","tryCatchPattern":null,"preventionTips":["Always scaffold app/root.tsx in new projects.","Verify react-router.config.ts appDirectory resolves to the folder containing root.tsx.","Add a CI check that asserts root.tsx exists."],"tags":["fs-routes","flat-routes","root-route","config"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}