
Fix “Can’t Modify Immutable Headers” in Astro on Cloudflare
Why cached Cloudflare Worker responses have immutable headers in Astro middleware, and the safe Response-cloning pattern that prevents the production error.
If Astro on Cloudflare throws “Can’t modify immutable headers” only on a cache hit, the cache is often working correctly. The problem is returning its Response object directly into a later framework step that needs to add or finalize headers.
Why a cache hit differs from a fresh response
Cloudflare’s runtime exposes web-standard Response and Headers objects. Responses returned by the Cache API can have immutable headers. Astro middleware, meanwhile, may finalize a response by adding headers after your middleware returns it. Those two behaviors collide only on the cached path.
Return a mutable equivalent
Copy the cached response into a new Response before returning it. This preserves the body, status, status text, and existing headers while giving the downstream framework a mutable header collection.
function toMutableResponse(response: Response) {
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: new Headers(response.headers),
})
}
const cached = await caches.default.match(cacheKey)
if (cached) return toMutableResponse(cached)Do not consume the body first
A Response body is a stream. Do not call cached.text(), cached.json(), or cached.arrayBuffer() before passing it into the new Response unless you deliberately create a new body from that data. The example transfers the untouched stream once.
Test the cache-hit path
A local first request can exercise the miss while the second request exercises the hit. In production, inspect the cache behavior and confirm both requests succeed. Test redirects, errors, and non-GET requests separately; they should not accidentally be stored as public page responses.
Do not disable caching to silence the error. Keep the cache hit, but make the response mutable at the boundary where Astro needs to finish it.
For the wider caching and invalidation design, read the fast Astro builds guide.
Reproduce the example
Open the repositoryReference: src/middleware.ts
npm installRequest a cache hit through the deployed Worker and confirm Astro can finalize the returned response without a header mutation error.Sources and further reading
- Middleware · Astro
- Headers · Cloudflare
- Cache · Cloudflare