withastro/astro · error · Error
the prerender server responded
Error message
the prerender server responded ${response.status} ${response.statusText}${details} What it means
During `astro build`, the Cloudflare adapter prerenders pages by fetching them from a local workerd-backed Vite preview server it starts on a random port. If that server answers with a non-OK status or no body, the build fails here; the message embeds the HTTP status and up to 200 characters of the (whitespace-collapsed) response body to expose the underlying failure. This is the Node-side mirror of a render failure that happened inside workerd.
Solutions
- Read the body snippet in the message — it usually contains the real stack trace from inside workerd.
- Reproduce locally with `wrangler dev` (or `astro dev` with the adapter's platform proxy) and open the failing page to get the full error.
- Search the failing page, its layout, and middleware for Node-only APIs and replace them with runtime-agnostic or web-standard alternatives.
- If the page is not meant to be prerendered, set `export const prerender = false` on it.
- Update @astrojs/cloudflare and astro to matching latest versions.
Defensive patterns
Strategy: try-catch
Try / catch
import { build } from 'astro';
try {
await build({ root: './', logLevel: 'info' });
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
// messages embed 'the prerender server responded <status>' plus up to 200 chars of body
if (msg.includes('prerender server responded')) {
console.error('Workerd-side render failure — body snippet:', msg);
process.exitCode = 1;
} else throw e;
} Prevention
- Run pages through `wrangler dev` (or the adapter's dev platform) before build so workerd incompatibilities surface early.
- Avoid Node-only APIs in prerendered pages/layouts/middleware.
- Keep astro and @astrojs/cloudflare versions upgraded together.
When it happens
Trigger: Building with @astrojs/cloudflare while prerendering is enabled, and a page/middleware throws inside the workerd runtime, a route 404s on the internal server, or the response stream aborts so `response.ok` is false or `response.body` is null.
Common situations: A page works in `astro dev` (Node) but uses an API unavailable in workerd (fs, native modules, Node streams); middleware crashing for the prerendered route; a dependency with workerd-incompatible code paths; version mismatch between astro and the adapter.
Related errors
- Failed to get static paths from the Cloudflare prerender…
- Failed to prerender
- Failed to get static images from the Cloudflare prerender…
- Could not optimize " " with the Cloudflare IMAGES binding (…
- Failed to start the Cloudflare prerender server. The…
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/64f8ece20f44671c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/integrations/cloudflare/src/prerenderer.ts:148
sourcePath: string | undefined,
): Promise<void> {
const response = await fetch(createImageTransformUrl(serverUrl, originalPath, transform), {
method: 'POST',
// Remote images have no local original; the worker fetches those itself.
...(sourcePath
? {
body: Readable.toWeb(createReadStream(sourcePath)) as unknown as BodyInit,
// Required by Node's fetch whenever the body is a stream.
duplex: 'half',
}
: {}),
} as RequestInit);
if (!response.ok || !response.body) {
// The body can be a full error page, so keep only enough of it to be useful.
const body = (await response.text().catch(() => '')).replace(/\s+/g, ' ').trim();
const details = body ? `: ${body.slice(0, 200)}` : '';
throw new Error(
`the prerender server responded ${response.status} ${response.statusText}${details}`,
);
}
const outputPath = join(fileURLToPath(clientDir), finalPath);
await mkdir(dirname(outputPath), { recursive: true });
// `fetch` types the body as the DOM `ReadableStream`, which is structurally
// identical to but nominally distinct from the `node:stream/web` one.
const body = response.body as unknown as NodeReadableStream<Uint8Array>;
await pipeline(Readable.fromWeb(body), createWriteStream(outputPath));
}
/**
* Creates a prerenderer that uses Cloudflare's workerd runtime via a preview server.
* This allows prerendering to happen in the same runtime that will serve the pages.
*/
export function createCloudflarePrerenderer({
root,View on GitHub (pinned to e294953aa8)