remix-run/react-router · error · Error
Unable to fetch new route matches from the server
Error message
Unable to fetch new route matches from the server
What it means
With lazy route discovery (the default in RSC framework mode), navigating to a path the client hasn't seen triggers a manifest fetch (`/__manifest`) to learn new routes. If that fetch fails at the transport level — no body, or a status outside 200–299 — this error is thrown and the navigation errors into the boundary. The 204 + `X-Remix-Reload-Document` case is handled separately as a version-mismatch reload, so plain 4xx/5xx or empty bodies are what land here.
Source
Thrown at packages/react-router/lib/rsc/browser.tsx:1096
// step and just let discovery happen on link click. We also wipe out the
// nextPaths Set here so we can start filling it with fresh links
if (url.toString().length > URL_LIMIT) {
nextPaths.clear();
return;
}
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) => {View on GitHub (pinned to 7aea711dd1)
Solutions
- Request the failing `/__manifest?p=...` URL directly and fix whatever answers it: ensure your server/adapter serves the manifest route, or deploy the generated manifest assets.
- Exclude `__manifest` from auth redirects so unauthenticated SPA navigations still discover routes (or accept the error boundary).
- If it only happens on stale tabs after a deploy, a hard reload resyncs route discovery.
- In tests, make sure any fetch mock returns a 200 with a manifest payload for the manifest URL.
Defensive patterns
Strategy: retry
Validate before calling
// deploy smoke test: manifest endpoint must be reachable
const res = await fetch(`${origin}/__manifest?p=${encodeURIComponent("/")}`);
if (!res.ok || !res.body) {
throw new Error(`route discovery broken: ${res.status}`);
} Try / catch
export function ErrorBoundary() {
const error = useRouteError();
if (error instanceof Error && /Unable to fetch new route matches/.test(error.message)) {
return <Link reloadDocument to="/">Retry</Link>; // full reload retries discovery
}
throw error;
} Prevention
- Ensure the server/adapter implements the __manifest route before enabling lazy route discovery.
- Don't put auth redirects in front of __manifest for SPA flows.
- Mock __manifest with a 200 manifest payload in tests.
When it happens
Trigger: The `/__manifest` endpoint returning 404/500 because a custom server or adapter doesn't implement it; auth middleware blocking the manifest request; deploys where manifest files are missing from the static host; offline or network-level failures during navigation to undiscovered routes.
Common situations: Custom servers/edge handlers that route everything to the app and never define `__manifest`; hosting that drops the manifest asset; tests stubbing fetch without covering the manifest URL; firewalls blocking the querystring-heavy manifest URLs.
Related errors
- Failed to patch routes
- ${res.status} ${res.statusText}
- No response body
- Unable to decode RSC response
- There was a problem fetching the file from GitHub. The reque
AI-assisted analysis of remix-run/react-router@7aea711dd1 (2026-08-18).
Data as JSON: /api/errors/15914658e43778cb.
Report an issue: GitHub.