{"record":{"id":"822f3cb6e12a78dd","repo":"remix-run/react-router","slug":"error-splitting-route-module-id-invalidchun","errorCode":null,"errorMessage":"Error splitting route module: ${id}\n\n${invalidChunks.map((name) => `- ${name}`).join(\"\\n\")}\n\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.","messagePattern":"Error splitting route module: (.+?)\n\n(.+?)`\\)\\.join\\(\"\\\\n\"\\)\\}\n\n(.+?) could not be split into (.+?) because (.+?) code with other exports\\. You should extract any shared code into its own module and then import it within the route module\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/rsc/virtual-route-modules.ts","lineNumber":550,"sourceCode":"\nfunction validateRouteChunks({\n  id,\n  valid,\n}: {\n  id: string;\n  valid: Record<Exclude<RouteChunkName, \"main\">, boolean>;\n}): void {\n  let invalidChunks = Object.entries(valid)\n    .filter(([_, isValid]) => !isValid)\n    .map(([chunkName]) => chunkName);\n\n  if (invalidChunks.length === 0) {\n    return;\n  }\n\n  let plural = invalidChunks.length > 1;\n\n  throw new Error(\n    [\n      `Error splitting route module: ${id}`,\n\n      invalidChunks.map((name) => `- ${name}`).join(\"\\n\"),\n\n      `${plural ? \"These exports\" : \"This export\"} could not be split into ${\n        plural ? \"their own chunks\" : \"its own chunk\"\n      } because ${\n        plural ? \"they share\" : \"it shares\"\n      } code with other exports. You should extract any shared code into its own module and then import it within the route module.`,\n    ].join(\"\\n\\n\"),\n  );\n}\n","sourceCodeStart":532,"sourceCodeEnd":564,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/rsc/virtual-route-modules.ts#L532-L564","documentation":"Thrown by validateRouteChunks in virtual-route-modules.ts when the RSC chunk-splitting pass cannot isolate one or more client-side exports (clientAction, clientLoader, clientMiddleware, HydrateFallback) into their own chunk because they share code with other exports. The error names the offending export(s) and the module id, then advises extracting shared code into a separate module. Only non-root routes are chunked.","triggerScenarios":"A non-root route module imports a shared helper or constant at module top-level and uses it from BOTH a server export (e.g. loader) and a client export (e.g. clientAction/HydrateFallback). The chunk analyzer marks that client export's chunk as invalid (shared code can't be split cleanly), and validateRouteChunks throws.","commonSituations":"A shared utility, constant, or type (especially runtime values) imported across the boundary between a loader and a clientAction/HydrateFallback. Co-locating shared validation logic used by both loader and clientAction. Bundler inlining a small shared value so both chunks retain it.","solutions":["Extract the shared code into its own module (separate file) and import it from both the server and client exports — the analyzer can then keep the shared module as a dependency rather than duplicating it.","If the shared value is only used by the client export, move it next to the client export so the server export no longer references it.","For types-only sharing, use `import type` so they are erased and don't couple chunks.","After refactoring, rebuild to let _detectRouteChunks re-evaluate chunk boundaries."],"exampleFix":"// app/routes/foo.tsx — before (shared helper couples loader + clientAction)\nimport { validate } from '~/utils/validate'; // runtime import shared across boundary\nexport async function loader() { validate(/* … */); /* … */ }\nexport async function clientAction() { validate(/* … */); /* … */ }\n// after — keep imports type-only where possible, or move runtime helper next to client export\n// app/routes/foo.tsx\nimport type { ValidateFn } from '~/utils/validate';\nimport { validate } from './foo.client'; // client-local module\nexport async function loader() { /* server-only validation */ }\nexport async function clientAction() { validate(/* … */); }","handlingStrategy":"validation","validationCode":"// crude heuristic: flag non-root route modules where a runtime import is shared\n// between a server export (loader/action/middleware) and a client export (clientAction/clientLoader/clientMiddleware/HydrateFallback)\nimport { parse } from '@babel/parser';\n// (implement a small AST check) — if a top-level runtime import is referenced in both groups, refactor","typeGuard":null,"tryCatchPattern":"try { await viteBuild(); }\ncatch (e) {\n  if (e instanceof Error && e.message.startsWith('Error splitting route module:')) {\n    // parse the listed export(s); extract shared code into a separate module and rebuild\n  }\n  throw e;\n}","preventionTips":["Keep server-only and client-only logic in separate files; import each into the route module.","Use `import type` for shared types so they don't couple chunks.","Avoid top-level runtime values shared across the loader/clientAction boundary."],"tags":["rsc","chunking","code-splitting","build-time","route-module"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}