remix-run/react-router · error
Module cannot have both a HydrateFallback export and a…
Error message
Module cannot have both a HydrateFallback export and a ServerHydrateFallback export
What it means
In RSC mode a route's loading UI can come from the client 'HydrateFallback' export or the server 'ServerHydrateFallback' export, never both. The framework-route wrapper picks the client variant first but throws when both are truthy, because which fallback renders during hydration would be ambiguous.
Solutions
- Keep only 'ServerHydrateFallback' for a server-rendered fallback
- Keep only 'HydrateFallback' for a client-only fallback
- Share fallback markup via a separate imported component
Example fix
// before
export function HydrateFallback() { return <Spinner />; }
export function ServerHydrateFallback() { return <ShellSpinner />; }
// after
export function HydrateFallback() { return <Spinner />; } Defensive patterns
Strategy: validation
Validate before calling
const PAIRS = [["HydrateFallback", "ServerHydrateFallback"]] as const;
for (const file of routeFiles) {
const mod: Record<string, unknown> = await import(pathToFileURL(file).href);
for (const [client, server] of PAIRS) {
if (mod[client] && mod[server]) {
throw new Error(`${file}: export either ${client} or ${server}, not both`);
}
}
} Type guard
function hasHydrateFallbackConflict(mod: Record<string, unknown>): boolean {
return Boolean(mod.HydrateFallback) && Boolean(mod.ServerHydrateFallback);
} Prevention
- Keep exactly one fallback export per route module
- When adding server fallbacks, remove the client fallback in the same change
- Run the RSC build in CI to catch the pair statically
When it happens
Trigger: A route module exporting both 'export function HydrateFallback()' and 'export function ServerHydrateFallback()' with both truthy.
Common situations: Adding a server-rendered fallback to a route that already declares a client HydrateFallback (common when routes use clientLoader and the fallback was later moved server-side).
Related errors
- Invalid route module exports. The following pairs of…
- Module cannot have both a default export and a…
- Module cannot have both a Layout export and a ServerLayout…
- Module cannot have both an ErrorBoundary export and a…
- Error splitting route module
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/265c7bb4cf3c1245.
Report an issue: GitHub.
Appendix: source
Thrown at packages/react-router-dev/vite/rsc/virtual-route-config.ts:50
throw new Error("Module cannot have both a Layout export and a ServerLayout export");
}
Layout = mod.Layout;
} else if ("ServerLayout" in mod && mod.ServerLayout) {
Layout = mod.ServerLayout;
}
if ("ErrorBoundary" in mod && mod.ErrorBoundary) {
if ("ServerErrorBoundary" in mod && mod.ServerErrorBoundary) {
throw new Error(
"Module cannot have both an ErrorBoundary export and a ServerErrorBoundary export",
);
}
ErrorBoundary = mod.ErrorBoundary;
} else if ("ServerErrorBoundary" in mod && mod.ServerErrorBoundary) {
ErrorBoundary = mod.ServerErrorBoundary;
}
if ("HydrateFallback" in mod && mod.HydrateFallback) {
if ("ServerHydrateFallback" in mod && mod.ServerHydrateFallback) {
throw new Error(
"Module cannot have both a HydrateFallback export and a ServerHydrateFallback export",
);
}
HydrateFallback = mod.HydrateFallback;
} else if ("ServerHydrateFallback" in mod && mod.ServerHydrateFallback) {
HydrateFallback = mod.ServerHydrateFallback;
}
const {
action,
clientAction,
clientLoader,
clientMiddleware,
handle,
headers,
links,
loader,
meta,View on GitHub (pinned to 6beaca3952)