remix-run/react-router · error
Error splitting route module: ${id} - ${name} This export
Error message
Error splitting route module: ${id}
- ${name}
This export could not be split into its own chunk because it shares code with other exports. You should extract any shared code into its own module and then import it within the route module. What it means
With `splitRouteModules` enabled, React Router tries to split a route module into separate chunks (clientLoader, clientAction, clientMiddleware, HydrateFallback) so navigation only downloads the code it needs. After splitting, it validates each generated chunk; if an export shares module-level code with others (helpers, constants, React components used by both the main module and a split export), the split is unsafe and the build fails, telling you exactly which exports could not be isolated.
Source
Thrown at packages/react-router-dev/vite/plugin.ts:3356
ctx: ReactRouterPluginContext;
id: string;
valid: Record<Exclude<RouteChunkName, "main">, boolean>;
}): void {
if (isRootRouteModuleId(ctx, id)) {
return;
}
let invalidChunks = Object.entries(valid)
.filter(([_, isValid]) => !isValid)
.map(([chunkName]) => chunkName);
if (invalidChunks.length === 0) {
return;
}
let plural = invalidChunks.length > 1;
throw new Error(
[
`Error splitting route module: ${normalizeRelativeFilePath(
id,
ctx.reactRouterConfig,
)}`,
invalidChunks.map((name) => `- ${name}`).join("\n"),
`${plural ? "These exports" : "This export"} could not be split into ${
plural ? "their own chunks" : "its own chunk"
} because ${
plural ? "they share" : "it shares"
} code with other exports. You should extract any shared code into its own module and then import it within the route module.`,
].join("\n\n"),
);
}
export async function cleanBuildDirectory(View on GitHub (pinned to 6beaca3952)
Solutions
- Extract code shared between the default export and split exports (clientLoader/clientAction/HydrateFallback/clientMiddleware) into its own module and import it from both sides
- Alternatively, disable `splitRouteModules` in react-router.config.ts if the refactor is not worth it
Example fix
// before (app/routes/todos.tsx) — shared helper blocks splitting
async function fetchTodos() { /* ... */ }
export async function clientLoader() { return { todos: await fetchTodos() }; }
export default function Todos({ loaderData }) { /* uses loaderData only */ }
// after — app/lib/todos.ts
export async function fetchTodos() { /* ... */ }
// app/routes/todos.tsx
import { fetchTodos } from '~/lib/todos';
export async function clientLoader() { return { todos: await fetchTodos() }; }
export default function Todos() { /* ... */ } Defensive patterns
Strategy: validation
Validate before calling
// Before enabling splitRouteModules, ensure shared module-scope bindings // are not referenced by both default and split exports (lint rule sketch) // eslint-disable-next-line @typescript-eslint/no-unused-vars const sharesModuleScopeCode = (src: string): boolean => /(?:^|\n)(?:async\s+)?(?:function|const|let|class)\s+\w+/.test(src) && /export\s+(?:async\s+)?(?:function|const)\s+(?:clientLoader|clientAction|clientMiddleware|HydrateFallback)/.test(src);
Try / catch
try {
await build();
} catch (e) {
if (e instanceof Error && e.message.startsWith('Error splitting route module')) {
// message names the file + exports — extract shared helpers into ~/lib and rebuild
}
} Prevention
- Keep route files thin: shared helpers live in `app/lib/*`, routes only import them
- Enable `splitRouteModules` on a clean branch and let CI validate all routes
- Avoid module-scope mutable state inside route files
When it happens
Trigger: `splitRouteModules: true` (or a config enabling it) where `clientLoader` references a helper also used by the component in the same file; a `HydrateFallback` component and the default export share a constants/functions defined at module scope; module-side effects or shared variables spanning exports.
Common situations: Adopting the route-module chunk splitting optimization on existing fat route files; single-file routes that colocate API helpers, types-instantiated at runtime, and UI; enabling the option globally and hitting one legacy route.
Related errors
- Error splitting route module: ${id} - ${name} This export
- React Router Vite plugin not found in Vite config
- Custom Vite manifest paths are not supported
- The React Router Vite plugin requires the use of a Vite conf
- Prerender (data): Received a ${response.status} status code
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/a4fb29491beacf79.
Report an issue: GitHub.