{"record":{"id":"c35f3f962d49791c","repo":"remix-run/react-router","slug":"error-splitting-route-module-normalizerelativef","errorCode":null,"errorMessage":"Error splitting route module: ${normalizeRelativeFilePath(id, ctx.reactRouterConfig)}\\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/plugin.ts","lineNumber":3356,"sourceCode":"  ctx: ReactRouterPluginContext;\n  id: string;\n  valid: Record<Exclude<RouteChunkName, \"main\">, boolean>;\n}): void {\n  if (isRootRouteModuleId(ctx, id)) {\n    return;\n  }\n\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: ${normalizeRelativeFilePath(\n        id,\n        ctx.reactRouterConfig,\n      )}`,\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\nexport async function cleanBuildDirectory(","sourceCodeStart":3338,"sourceCodeEnd":3374,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/plugin.ts#L3338-L3374","documentation":"Thrown by `validateRouteChunks` when one or more named route chunks (`clientAction`, `clientLoader`, `HydrateFallback`, `ErrorBoundary`) cannot be safely isolated. React Router splits these exports into separate chunks so the client doesn't download, e.g., the action code on first paint. If an export shares code (variables, helper functions, imports) with another export, the splitter would have to duplicate or pull in shared code, so it refuses and lists the offending chunk names.","triggerScenarios":"A route module declares `clientAction` and `clientLoader` that both reference a shared in-file helper or a shared top-level `const`; an `ErrorBoundary` that imports a large shared module also used by the route's `default`; route chunks that close over module-scope mutable state.","commonSituations":"Co-locating action/loader logic in one route file with shared helpers; refactoring that pulls shared utilities up to module scope; large route modules with intertwined exports.","solutions":["Extract the shared code into its own module (a sibling `.ts` file) and import it from each export.","Inline the shared logic per export if extraction is not desirable.","Reduce cross-export coupling by passing data through arguments instead of module-scope variables.","Rebuild — the listed chunk names tell you exactly which exports to refactor."],"exampleFix":"// before: clientAction and clientLoader share a helper\nconst fetcher = (id) => api.get(`/x/${id}`);\nexport const clientAction = () => fetcher(1);\nexport const clientLoader = () => fetcher(2);\n// after: extract shared helper\n// app/routes/_shared.ts\nexport const fetcher = (id) => api.get(`/x/${id}`);\n// app/routes/foo.ts\nimport { fetcher } from \"./_shared\";\nexport const clientAction = () => fetcher(1);\nexport const clientLoader = () => fetcher(2);","handlingStrategy":"validation","validationCode":"// Statically detect shared top-level identifiers across chunks\nconst findSharedBindings = (exports: string[], moduleScope: string[]) => {\n  return moduleScope.filter(name =>\n    exports.some(e => references(name, e)) &&\n    exports.some(e => e !== references && references(name, e)));\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Extract shared helpers between `clientAction`/`clientLoader`/`ErrorBoundary` into separate files.","Avoid module-scope mutable state shared across route chunks.","Run a pre-build static analysis pass that flags shared identifiers across named chunks."],"tags":["route-chunks","build","code-splitting","route-exports"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}