remix-run/react-router · error · Error
Could not find a root route module in the app directory: ${a
Error message
Could not find a root route module in the app directory: ${appDirectory} What it means
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.
Source
Thrown at packages/react-router-fs-routes/flatRoutes.ts:87
return values;
}
}
export function flatRoutes(
appDirectory: string,
ignoredFilePatterns: string[] = [],
prefix = "routes",
) {
let ignoredFileRegex = Array.from(new Set(["**/.*", ...ignoredFilePatterns]))
.map((re) => makeRe(re))
.filter((re: any): re is RegExp => !!re);
let routesDir = path.join(appDirectory, prefix);
let rootRoute = findFile(appDirectory, "root", routeModuleExts);
if (!rootRoute) {
throw new Error(
`Could not find a root route module in the app directory: ${appDirectory}`,
);
}
if (!fs.existsSync(routesDir)) {
throw new Error(
`Could not find the routes directory: ${routesDir}. Did you forget to create it?`,
);
}
// Only read the routes directory
let entries = fs.readdirSync(routesDir, {
withFileTypes: true,
encoding: "utf-8",
});
let routes: string[] = [];
for (let entry of entries) {View on GitHub (pinned to 1fd704a7da)
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).
Example fix
// before: app/ has only routes/, no root file → create app/root.tsx
// app/root.tsx
import { Outlet } from 'react-router';
export default function Root() {
return (<html><body><Outlet/></body></html>);
} Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
import { exts } from './routeModuleExts'; // mimic the supported list: ts,tsx,js,jsx,mdx,...
function hasRootRoute(appDirectory: string): boolean {
return ['ts','tsx','js','jsx','mdx'].some((e) => existsSync(`${appDirectory}/root.${e}`));
}
if (!hasRootRoute(appDirectory)) throw new Error('Missing app/root.tsx'); Type guard
function appDirectoryHasRoot(appDirectory: string, exts: string[]): boolean {
const { existsSync } = require('node:fs');
return exts.some((e) => existsSync(`${appDirectory}/root.${e}`));
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Could not find the routes directory: ${routesDir}. Did you f
- Route segment "${segment}" for "${routeId}" cannot contain "
- React Router presets must have a `name` property defined.
- Could not find package.json in ${rootDirectory} or any of it
- Unable to define routes with duplicate route id: "${id}"
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/c92164f789294d7a.
Report an issue: GitHub.