{"record":{"id":"3156b2d1b99a0495","repo":"withastro/astro","slug":"astroresponseheadersreassigned","errorCode":"AstroResponseHeadersReassigned","errorMessage":"Individual headers can be added to and removed from `Astro.response.headers`, but it must not be replaced with another instance of `Headers` altogether.","messagePattern":"Individual headers can be added to and removed from `Astro\\.response\\.headers`, but it must not be replaced with another instance of `Headers` altogether\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/core/fetch/fetch-state.ts","lineNumber":441,"sourceCode":"\t\t\t}\n\t\t}\n\n\t\tconst componentMetadata =\n\t\t\t(await env.componentMetadata(manifest, routeData)) ?? manifest.componentMetadata;\n\t\tconst headers = new Headers({ 'Content-Type': 'text/html' });\n\t\tconst partial = typeof this.partial === 'boolean' ? this.partial : Boolean(mod.partial);\n\t\tconst actionResult = hasActionPayload(this.locals)\n\t\t\t? deserializeActionResult(this.locals._actionPayload.actionResult)\n\t\t\t: undefined;\n\t\tconst status = this.status;\n\t\tconst response = {\n\t\t\tstatus: actionResult?.error ? actionResult?.error.status : status,\n\t\t\tstatusText: actionResult?.error ? actionResult?.error.type : 'OK',\n\t\t\tget headers() {\n\t\t\t\treturn headers;\n\t\t\t},\n\t\t\tset headers(_) {\n\t\t\t\tthrow new AstroError(AstroErrorData.AstroResponseHeadersReassigned);\n\t\t\t},\n\t\t} satisfies AstroGlobal['response'];\n\n\t\tconst state = this;\n\t\tconst result: SSRResult = {\n\t\t\tbase: manifest.base,\n\t\t\tuserAssetsBase: manifest.userAssetsBase,\n\t\t\tcancelled: false,\n\t\t\tclientDirectives,\n\t\t\tinlinedScripts,\n\t\t\tcomponentMetadata,\n\t\t\tcompressHTML,\n\t\t\tcookies: this.cookies,\n\t\t\tcreateAstro: (props, slots) => state.createAstro(result, props, slots, ctx),\n\t\t\tlinks,\n\t\t\t// SAFETY: createResult is only called after route resolution, so routeData\n\t\t\t// is always set and the params getter always returns a value.\n\t\t\tparams: this.params!,","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/core/fetch/fetch-state.ts#L423-L459","documentation":"On the fetch-state-backed Astro global, Astro.response.headers is defined with a getter only; the setter always throws AstroErrorData.AstroResponseHeadersReassigned. Astro forbids replacing the Headers instance because the rest of the render pipeline (cookies, actions, routing) already holds a reference to that exact object. Individual headers may still be added, changed, or removed in place.","triggerScenarios":"Any whole-object assignment in .astro frontmatter, middleware, or actions: Astro.response.headers = new Headers({...}), or assigning a Headers object built elsewhere (a helper function that returns new Headers() and is then assigned).","commonSituations":"Porting code from Express/Next-style frameworks where replacing the response or its headers is idiomatic; refactors that build a Headers object in a utility and assign it on the Astro global; copy-pasted snippets from tutorials targeting other stacks.","solutions":["Mutate the existing instance in place: Astro.response.headers.set('name', 'value')","If you built a Headers or plain object elsewhere, copy its entries onto Astro.response.headers with set/append instead of assigning","Use Astro.response.status / statusText for the other response fields — only the headers instance is protected"],"exampleFix":"// before\nAstro.response.headers = new Headers({ 'x-cache': 'miss' });\n\n// after\nAstro.response.headers.set('x-cache', 'miss');","handlingStrategy":"validation","validationCode":"function applyResponseHeaders(source: Headers | Record<string, string>): void {\n  const target = Astro.response.headers;\n  if (source instanceof Headers) {\n    for (const [name, value] of source) target.set(name, value);\n  } else {\n    for (const [name, value] of Object.entries(source)) target.set(name, value);\n  }\n}\n// use: applyResponseHeaders(new Headers({ 'x-cache': 'miss' })) instead of assigning","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat Astro.response.headers as read-only reference; only call set/append/delete/append on it","Build headers in helpers that return plain objects and merge them with the pattern above","Grep the codebase for 'Astro.response.headers =' after porting code from other frameworks"],"tags":["astro-global","response-headers","readonly-property","assignment"],"backgroundTag":"readonly-property-reassignment","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}