remix-run/react-router · error · Error

The "serverBundles" function must return a string

Error message

The "serverBundles" function must return a string

What it means

Thrown while building the server-bundle manifest. The user-supplied `serverBundles({ branch })` config function must return a string ID naming the bundle the route branch belongs to. A non-string return (undefined, number, object, Promise of non-string) breaks manifest construction because the ID is used as a Vite environment name and a manifest key.

Source

Thrown at packages/react-router-dev/vite/plugin.ts:3465

    serverBundles: {},
    routeIdToServerBundleId: {},
    routes: rootRelativeRoutes,
  };

  await Promise.all(
    getAddressableRoutes(routes).map(async (route) => {
      let branch = getRouteBranch(routes, route.id);
      let serverBundleId = await serverBundles({
        branch: branch.map((route) =>
          configRouteToBranchRoute({
            ...route,
            // Ensure absolute paths are passed to the serverBundles function
            file: path.join(resolvedAppDirectory, route.file),
          }),
        ),
      });
      if (typeof serverBundleId !== "string") {
        throw new Error(`The "serverBundles" function must return a string`);
      }
      // Server bundle IDs must be valid Vite environment names, so hyphens are not allowed
      if (!/^[a-zA-Z0-9_]+$/.test(serverBundleId)) {
        throw new Error(
          `The "serverBundles" function must only return strings containing alphanumeric characters and underscores.`,
        );
      }
      buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;

      buildManifest.serverBundles[serverBundleId] ??= {
        id: serverBundleId,
        file: normalizePath(
          path.join(
            path.relative(
              rootDirectory,
              path.join(serverBuildDirectory, serverBundleId),
            ),
            reactRouterConfig.serverBuildFile,

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Ensure every code path in `serverBundles` returns a string.
  2. Add a default return at the end (e.g. `return "root";`).
  3. Annotate the function's return type as `Promise<string> | string` so TypeScript flags missing returns.
  4. Unit-test the function over all branches before running the full build.

Example fix

// before
export const serverBundles = async ({ branch }) => {
  if (branch.some(r => r.id === "admin")) "admin"; // forgot return
};
// after
export const serverBundles = async ({ branch }): Promise<string> => {
  if (branch.some(r => r.id === "admin")) return "admin";
  return "root";
};
Defensive patterns

Strategy: type-guard

Type guard

const isServerBundleId = (v: unknown): v is string =>
  typeof v === "string" && v.length > 0;

Prevention

When it happens

Trigger: A `serverBundles` function that forgets to `return` (implicitly returns `undefined`); returns a number/object; an async function whose awaited value is not a string; branching logic that returns nothing on some paths.

Common situations: Authoring `serverBundles` for the first time; refactoring the function and dropping a return; early-return guard clauses that miss a branch.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/8d7b2a0349fc8827. Report an issue: GitHub.