{"record":{"id":"a721cd6ac55d6210","repo":"remix-run/react-router","slug":"module-cannot-have-both-a-default-export-and-a-ser","errorCode":null,"errorMessage":"Module cannot have both a default export and a ServerComponent export","messagePattern":"Module cannot have both a default export and a ServerComponent export","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/rsc/virtual-route-config.ts","lineNumber":24,"sourceCode":"export function createVirtualRouteConfig({\n  appDirectory,\n  routeConfig,\n}: {\n  appDirectory: string;\n  routeConfig: RouteConfigEntry[];\n}): { code: string; routeIdByFile: Map<string, string> } {\n  let routeIdByFile = new Map<string, string>();\n  let code = js`import * as React from \"react\";\nfunction frameworkRoute(lazy) {\n  return async () => {\n    const mod = await lazy();\n    let Component;\n    let Layout;\n    let ErrorBoundary;\n    let HydrateFallback;\n    if (\"default\" in mod && mod.default) {\n      if (\"ServerComponent\" in mod && mod.ServerComponent) {\n        throw new Error(\"Module cannot have both a default export and a ServerComponent export\");\n      }\n      Component = mod.default;\n    } else if (\"ServerComponent\" in mod && mod.ServerComponent) {\n      Component = mod.ServerComponent;\n    }\n    if (\"Layout\" in mod && mod.Layout) {\n      if (\"ServerLayout\" in mod && mod.ServerLayout) {\n        throw new Error(\"Module cannot have both a Layout export and a ServerLayout export\");\n      }\n      Layout = mod.Layout;\n    } else if (\"ServerLayout\" in mod && mod.ServerLayout) {\n      Layout = mod.ServerLayout;\n    }\n    if (\"ErrorBoundary\" in mod && mod.ErrorBoundary) {\n      if (\"ServerErrorBoundary\" in mod && mod.ServerErrorBoundary) {\n        throw new Error(\n          \"Module cannot have both an ErrorBoundary export and a ServerErrorBoundary export\",\n        );","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router-dev/vite/rsc/virtual-route-config.ts#L6-L42","documentation":"Runtime guard inside the generated frameworkRoute() wrapper (virtual-route-config.ts) for RSC Framework Mode. A route module may export either a client `default` component OR a `ServerComponent`, but not both — the runtime cannot decide which to render on each side. This check executes in the browser/server bundle when the route module loads.","triggerScenarios":"A single route module file (e.g. app/routes/foo.tsx) has both `export default function Foo()` and `export function ServerComponent()`. The frameworkRoute wrapper's `if ('default' in mod && mod.default)` branch then checks for ServerComponent and throws.","commonSituations":"Refactoring a client component into an RSC and forgetting to remove the default export. Copy-pasting a hybrid example. Tooling (codemods) that auto-adds ServerComponent without removing default.","solutions":["In the offending route module, choose ONE: keep `export default` for a client component, or rename it to `export function ServerComponent` for a server component.","Use `pnpm react-router typegen` to surface the conflict at compile time too (it shares the MUTUALLY_EXCLUSIVE_ROUTE_EXPORTS table).","Re-run dev/build after editing to confirm the runtime guard no longer fires."],"exampleFix":"// app/routes/foo.tsx\n// before\nexport default function Foo() { return <p>client</p>; }\nexport function ServerComponent() { return <p>server</p>; }\n// after (server component only)\nexport function ServerComponent() { return <p>server</p>; }","handlingStrategy":"validation","validationCode":"// build-time check: scan route modules for the conflicting pair\nimport { readFileSync } from 'node:fs';\nconst src = readFileSync(routeFile, 'utf8');\nconst hasDefault = /export\\s+default\\s/.test(src);\nconst hasServerComponent = /export\\s+(async\\s+)?function\\s+ServerComponent\\b/.test(src);\nif (hasDefault && hasServerComponent) throw new Error(`${routeFile}: cannot export both default and ServerComponent`);","typeGuard":"function moduleExportsOnlyOneComponent(mod: Record<string, unknown>): boolean {\n  return !mod.default || !mod.ServerComponent;\n}","tryCatchPattern":null,"preventionTips":["Adopt a lint rule banning both exports in one file.","Run typegen after refactors — it flags these via MUTUALLY_EXCLUSIVE_ROUTE_EXPORTS."],"tags":["rsc","route-module","exports","framework-mode"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}