remix-run/react-router · error · Error

Failed to patch routes

Error message

Failed to patch routes

What it means

After a successful manifest fetch for lazy route discovery, the decoded payload must have `type: "manifest"`; anything else throws this error before routes are patched. The transport succeeded, but the server answered the `__manifest` request with a different payload type (usually a render payload from an HTML fallback or an action/redirect payload).

Source

Thrown at packages/react-router/lib/rsc/browser.tsx:1103

  let response = await fetchImplementation(new Request(url, { signal }));
  if (
    clientVersion !== undefined &&
    response.status === 204 &&
    response.headers.has("X-Remix-Reload-Document")
  ) {
    await handleClientVersionMismatch(true, clientVersion, errorReloadPath);
    return;
  }

  if (!response.body || response.status < 200 || response.status >= 300) {
    throw new Error("Unable to fetch new route matches from the server");
  }

  let payload = (await createFromReadableStream(response.body, {
    temporaryReferences: undefined,
  })) as RSCPayload;
  if (payload.type !== "manifest") {
    throw new Error("Failed to patch routes");
  }

  // Track discovered paths so we don't have to fetch them again
  paths.forEach((p) => addToFifoQueue(p, discoveredPaths));

  let patches = await payload.patches;

  // Without the `allowElementMutations` flag, this will no-op if the route
  // already exists so we can just call it for all returned patches
  React.startTransition(() => {
    patches.forEach((p) => {
      (window as WindowWithRouterGlobals).__reactRouterDataRouter.patchRoutes(
        p.parentId ?? null,
        [createRouteFromServerManifest(p)],
      );
    });
  });
}

View on GitHub (pinned to 7aea711dd1)

Solutions

  1. Verify `/__manifest?p=...` returns a manifest payload (type `manifest` with `patches`), not HTML or a redirect.
  2. Fix custom server routing so `__manifest` requests reach the route-discovery handler instead of a document fallback.
  3. Ensure auth guards redirect only document requests, and let manifest requests through or answer them properly.
  4. Purge CDN caches of `__manifest` URLs after each deploy.
Defensive patterns

Strategy: fallback

Validate before calling

// verify the manifest endpoint returns the right payload kind
const payload = await res.json();
if (payload?.type !== "manifest") {
  throw new Error(`__manifest returned type=${payload?.type}`);
}

Type guard

const isManifestPayload = (p: unknown): p is { type: "manifest" } =>
  (p as { type?: string })?.type === "manifest";

Try / catch

export function ErrorBoundary() {
  const error = useRouteError();
  if (error instanceof Error && error.message === "Failed to patch routes") {
    return <Link reloadDocument to={location.pathname}>Reload</Link>;
  }
  throw error;
}

Prevention

When it happens

Trigger: A custom server routing `__manifest` requests into the SSR/document handler so a render payload comes back; auth redirects rewriting the manifest request into a redirect payload; CDN/edge workers caching a navigation response for the manifest URL; version skew where old manifest URLs hit a new server's fallback.

Common situations: Hand-rolled servers that don't special-case `__manifest`; catch-all handlers returning the app shell for every path; test fetch mocks returning the wrong payload type; mid-deploy cache poisoning keyed only by URL.

Related errors


AI-assisted analysis of remix-run/react-router@7aea711dd1 (2026-08-18). Data as JSON: /api/errors/d4b4f33dd04116e0. Report an issue: GitHub.