remix-run/react-router · error · Error

${res.status} ${res.statusText}

Error message

${res.status} ${res.statusText}

What it means

In SPA/lazy-route 'fog of war' discovery, the client fetched a manifest patch from the server and received a non-2xx response. The thrown Error carries `${res.status} ${res.statusText}` so callers see the raw HTTP failure, then it propagates up unless the request was aborted.

Source

Thrown at packages/react-router/lib/dom/ssr/fog-of-war.ts:342

    getManifestPath(manifestPath, basename),
    window.location.origin,
  );
  url.search = searchParams.toString();

  // If the URL is nearing the ~8k limit on GET requests, skip this optimization
  // 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 serverPatches: AssetsManifest["routes"];
  try {
    let res = await fetch(url, { signal });

    if (!res.ok) {
      throw new Error(`${res.status} ${res.statusText}`);
    }

    if (
      await handleClientVersionMismatch(
        res.status === 204 && res.headers.has("X-Remix-Reload-Document"),
        manifest.version,
        errorReloadPath,
      )
    ) {
      return;
    }

    serverPatches = (await res.json()) as AssetsManifest["routes"];
  } catch (e) {
    if (signal?.aborted) return;
    throw e;
  }

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Open the failing patch URL directly in the browser/network tab to see the body and confirm which layer (proxy/CDN/app) returns the error.
  2. Ensure the configured `manifestPath` is served by your host and not blocked by auth or rewrite rules.
  3. Redeploy so client and server share the same build version (clears version-mismatch reload loops).
  4. If behind a CDN, allowlist the manifest path or disable caching on it.
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe the manifest patch endpoint at startup in production
async function pingManifest(url: string) {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`manifest endpoint ${res.status}`);
}
await pingManifest(`${origin}/__manifest?paths=/&version=${BUILD_VERSION}`);

Try / catch

try {
  await fetchAndApplyManifestPatches(...);
} catch (e) {
  if (signal?.aborted) return;
  // degrade gracefully: route will be discovered on click instead
  console.warn('manifest patch failed', e);
}

Prevention

When it happens

Trigger: `fetchAndApplyManifestPatches` calls the manifest patch endpoint (the configured `manifestPath`) and `res.ok` is false. Happens when the dev/asset server returns 4xx/5xx for the patch URL, e.g. behind a reverse proxy that blocks the path, a stale build whose manifest endpoint moved, or an auth/CDN layer returning 403/404.

Common situations: Deploying a SPA build behind nginx/CDN that doesn't route the manifest patch path; version skew between client bundle and server manifest; the manifest endpoint returning 500 due to a misconfigured asset server; running a very old client bundle against a newer server.

Related errors


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