remix-run/react-router · error · Error

Prerender: Request failed for ${prerenderPath}: ${response.s

Error message

Prerender: Request failed for ${prerenderPath}: ${response.status} ${response.statusText}

What it means

Thrown by `defaultPostProcess` (the plugin's built-in post-processor) when the prerender request's response is not `response.ok` (i.e. status outside 200–299). Unlike the typed `metadata` post-processor in `plugin.ts`, this default handler is used when no custom `postProcess` is configured; it cannot interpret non-200 bodies, so it aborts with the status code and reason.

Source

Thrown at packages/react-router-dev/vite/plugins/prerender.ts:424

            },
          },
        };
      },
    },
    configResolved(resolvedConfig) {
      viteConfig = resolvedConfig;
    },
  };
}

async function defaultPostProcess(
  request: Request,
  response: Response,
): Promise<PrerenderFile[]> {
  const prerenderPath = new URL(request.url).pathname;

  if (!response.ok) {
    throw new Error(
      `Prerender: Request failed for ${prerenderPath}: ${response.status} ${response.statusText}`,
    );
  }

  return [
    {
      path: `${prerenderPath}/index.html`,
      contents: await response.text(),
    },
  ];
}

function defaultHandleError(request: Request, error: Error): void {
  const prerenderPath = new URL(request.url).pathname;

  if (request.signal?.aborted) {
    throw new Error(
      `Prerender: Request timed out for ${prerenderPath}: ${error.message}`,

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Reproduce by running `react-router build` then `react-router preview` and fetching the printed path.
  2. Make the loader/renderer return 200 for prerendered paths at build time.
  3. Implement a custom `postProcess` if you need to tolerate non-200 (e.g. write the error page to disk intentionally).
  4. Remove the path from `prerender` if it cannot succeed at build time.

Example fix

// before: loader returns 404 for a prerendered path
export const loader = ({ params }) => {
  if (!params.slug) return new Response(null, { status: 404 });
};
// after
export const loader = ({ params }) => {
  return json({ slug: params.slug ?? "home" });
};
Defensive patterns

Strategy: try-catch

Validate before calling

const assertOk = (res: Response, path: string) => {
  if (!res.ok) throw new Error(`prerender ${path} -> ${res.status}`);
};

Try / catch

try {
  await prerender(cfg);
} catch (e) {
  if (/Prerender: Request failed for/.test(String(e.message))) {
    // log full context, optionally skip the path and continue
    console.warn(e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: A prerendered route returns 4xx/5xx from the preview server during the prerender pass; the route's loader throws; `entry.server.tsx` returns an error response; a resource route that 404s during prerender.

Common situations: CI build where the loader fails on missing env data; a route that conditionally returns 404; preview server misconfigured (wrong port/hostname) so requests 502.

Related errors


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