remix-run/react-router · error

Error splitting route module: ${id} - ${name} This export

Error message

Error splitting route module: ${id}

- ${name}

This export could not be split into its own chunk because it shares code with other exports. You should extract any shared code into its own module and then import it within the route module.

What it means

In RSC mode the Vite plugin splits each route module into separate chunks per export (loader, action, Component, clientLoader, ...) so server-only code never ships to the client. After splitting it validates that each export landed in its own chunk; when an export could not be isolated because it shares module-scope code (helpers, constants, instantiated clients) with other exports, the build fails naming the offending exports and telling you to extract the shared code into its own module.

Source

Thrown at packages/react-router-dev/vite/rsc/virtual-route-modules.ts:550

function validateRouteChunks({
  id,
  valid,
}: {
  id: string;
  valid: Record<Exclude<RouteChunkName, "main">, boolean>;
}): void {
  let invalidChunks = Object.entries(valid)
    .filter(([_, isValid]) => !isValid)
    .map(([chunkName]) => chunkName);

  if (invalidChunks.length === 0) {
    return;
  }

  let plural = invalidChunks.length > 1;

  throw new Error(
    [
      `Error splitting route module: ${id}`,

      invalidChunks.map((name) => `- ${name}`).join("\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.`,
    ].join("\n\n"),
  );
}

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Move the shared code into its own file (e.g. app/routes/post.data.ts) and import it from the route module
  2. If one of the exports is unnecessary (e.g. you don't need clientLoader), remove it so no split is required
  3. Re-run 'react-router build' — validation happens per route module, so fix routes one at a time as listed

Example fix

// before — app/routes/posts.$slug.tsx
async function loadPost(slug: string) { /* shared by both exports */ }
export async function loader({ params }) { return loadPost(params.slug); }
export async function clientLoader({ params }) { return loadPost(params.slug); }

// after — app/posts.shared.ts
export async function loadPost(slug: string) { /* ... */ }

// app/routes/posts.$slug.tsx
import { loadPost } from "../posts.shared";
export async function loader({ params }) { return loadPost(params.slug); }
export async function clientLoader({ params }) { return loadPost(params.slug); }
Defensive patterns

Strategy: validation

Validate before calling

// no cheap pre-check exists — use the build itself as the validator in CI
// .github/workflows/ci.yml
// - run: pnpm install --frozen-lockfile
// - run: pnpm build   # the RSC splitter validates every route module here

Prevention

When it happens

Trigger: A route module declares a helper or constant at module top level that is referenced from two or more special exports — e.g. 'const db = createDb()' used by both 'loader' and 'clientLoader', or a shared 'loadPost()' function — so the splitter cannot separate the chunks.

Common situations: Writing loader + clientLoader pairs that share a local data function; refactoring that hoists shared constants into the route module; moving server client instantiation into the route file for convenience.

Related errors


AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18). Data as JSON: /api/errors/2dac8fdefe14715f. Report an issue: GitHub.