{"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":"validation","errorClass":null,"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/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/rsc/virtual-route-config.ts#L6-L42","documentation":"In RSC mode, route modules are split into client and server portions, and a route's component can be supplied either by the client 'default' export or by the server 'ServerComponent' export — never both. The generated framework-route wrapper checks the module at render time: when 'default' is truthy and 'ServerComponent' is also present it throws, because it would be ambiguous which component should render.","triggerScenarios":"A route module containing both 'export default function Route()' and 'export async function ServerComponent()' (both truthy at module-evaluation time in the lazy-loaded route).","commonSituations":"Converting an existing Framework-mode route to RSC by adding ServerComponent while forgetting to delete the old default export; copy-pasting from examples that mix client and server component conventions in one file.","solutions":["Delete the 'default' export if the route should render on the server","Delete 'ServerComponent' if the route must stay a client component","Move any shared JSX/helpers into a separate imported module so only one component export remains"],"exampleFix":"// before — app/routes/dashboard.tsx\nexport default function Route() { return <h1>Client</h1>; }\nexport async function ServerComponent() { return <h1>Server</h1>; }\n\n// after\nexport async function ServerComponent() { return <h1>Server</h1>; }","handlingStrategy":"validation","validationCode":"// dev-time scan: import each route module and check export pairs\nconst PAIRS = [[\"default\", \"ServerComponent\"]] as const;\nfor (const file of routeFiles) {\n  const mod: Record<string, unknown> = await import(pathToFileURL(file).href);\n  for (const [client, server] of PAIRS) {\n    if (mod[client] && mod[server]) {\n      throw new Error(`${file}: export either ${client} or ${server}, not both`);\n    }\n  }\n}","typeGuard":"function hasComponentConflict(mod: Record<string, unknown>): boolean {\n  return Boolean(mod.default) && Boolean(mod.ServerComponent);\n}","tryCatchPattern":null,"preventionTips":["When converting a route to RSC, delete the old default export in the same commit","Adopt a naming convention where a route uses either client or server variants exclusively","Run the RSC build in CI so the static pair validation (error 47) catches regressions"],"tags":["rsc","route-module","exports","server-component","naming"],"backgroundTag":"mutually-exclusive-exports","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}