{"record":{"id":"fbd8228a7555a53d","repo":"remix-run/react-router","slug":"could-not-find-the-routes-directory-routesdir","errorCode":null,"errorMessage":"Could not find the routes directory: ${routesDir}. Did you forget to create it?","messagePattern":"Could not find the routes directory: (.+?)\\. Did you forget to create it\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-fs-routes/flatRoutes.ts","lineNumber":93,"sourceCode":"  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) {\n    let filepath = normalizeSlashes(path.join(routesDir, entry.name));\n\n    let route: string | null = null;\n    // If it's a directory, don't recurse into it, instead just look for a route module\n    if (entry.isDirectory()) {\n      route = findRouteModuleForFolder(","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-fs-routes/flatRoutes.ts#L75-L111","documentation":"Thrown by flatRoutes() right after the root-route check: fs.existsSync(routesDir) is false, where routesDir = path.join(appDirectory, prefix) (prefix defaults to 'routes'). File-system routing requires the routes directory to exist, even if empty, because flatRoutes reads it with readdirSync.","triggerScenarios":"flatRoutes() runs against an app directory that has root.tsx but no `routes/` subdirectory. Also triggered by a custom `prefix` (e.g. 'app/routes' set via the second argument) whose target directory doesn't exist.","commonSituations":"New project where routes/ wasn't scaffolded. Renaming routes/ to pages/ without updating the prefix. Custom flatRoutes(prefix) call pointing at a non-existent folder. Empty app where the developer intends to add routes later.","solutions":["Create the directory: `mkdir app/routes` (use the prefix path if customized).","If you renamed the folder, either rename it back to `routes` or pass the new folder name as the `prefix` argument to flatRoutes().","Add at least an index route (app/routes/_index.tsx) so the directory is non-empty and the app has a landing route.","Re-run build/dev to confirm flatRoutes resolves."],"exampleFix":"// before: app/root.tsx exists but app/routes/ is missing\n// shell\nmkdir -p app/routes\n// optionally add app/routes/_index.tsx\n// after: app/routes/_index.tsx\nexport default function Index() { return <h1>Home</h1>; }","handlingStrategy":"validation","validationCode":"import { existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nconst routesDir = join(appDirectory, prefix ?? 'routes');\nif (!existsSync(routesDir)) mkdirSync(routesDir, { recursive: true });","typeGuard":"function routesDirectoryExists(appDirectory: string, prefix = 'routes'): boolean {\n  const { existsSync } = require('node:fs');\n  return existsSync(`${appDirectory}/${prefix}`);\n}","tryCatchPattern":null,"preventionTips":["Scaffold app/routes/ (or the configured prefix) in every new project.","If renaming the folder, update the flatRoutes prefix argument.","Add an index route file so the directory is non-empty."],"tags":["fs-routes","flat-routes","routes-directory","config"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}