{"record":{"id":"b7490bf2036eff9b","repo":"denoland/deno","slug":"cannot-change-headers-headers-are-immutable","errorCode":null,"errorMessage":"Cannot change headers: headers are immutable","messagePattern":"Cannot change headers: headers are immutable","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/20_headers.js","lineNumber":467,"sourceCode":"    name = webidl.converters[\"ByteString\"](name, prefix, \"Argument 1\");\n    value = webidl.converters[\"ByteString\"](value, prefix, \"Argument 2\");\n    appendHeader(this, name, value);\n  }\n\n  /**\n   * @param {string} name\n   */\n  delete(name) {\n    webidl.assertBranded(this, HeadersPrototype);\n    const prefix = \"Failed to execute 'delete' on 'Headers'\";\n    webidl.requiredArguments(arguments.length, 1, prefix);\n    name = webidl.converters[\"ByteString\"](name, prefix, \"Argument 1\");\n\n    if (!checkHeaderNameForHttpTokenCodePoint(name)) {\n      throw new TypeError(`Invalid header name: \"${name}\"`);\n    }\n    if (this[_guard] == \"immutable\") {\n      throw new TypeError(\"Cannot change headers: headers are immutable\");\n    }\n\n    const list = headerListFromHeaders(this);\n    const lowerNames = ensureLowerNames(this);\n    const lowercaseName = byteLowerCase(name);\n    let writeIdx = 0;\n    for (let i = 0; i < lowerNames.length; i++) {\n      if (lowerNames[i] !== lowercaseName) {\n        list[writeIdx] = list[i];\n        lowerNames[writeIdx] = lowerNames[i];\n        writeIdx++;\n      }\n    }\n    if (writeIdx !== list.length) {\n      ArrayPrototypeSplice(list, writeIdx);\n      ArrayPrototypeSplice(lowerNames, writeIdx);\n    }\n  }","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/20_headers.js#L449-L485","documentation":"Thrown by Headers.delete() when the Headers object has guard \"immutable\". In Deno, headers become immutable when they come from a network fetch Response (26_fetch.js wraps responses with guard \"immutable\") and from redirected/preserved responses. The guard check happens after name validation but before any mutation, so every delete() on such headers throws.","triggerScenarios":"`const res = await fetch(url); res.headers.delete(\"set-cookie\")`. Also headers of a Response created via fromInnerResponse with \"immutable\" guard (redirect handling, op_http responses preserved across restarts).","commonSituations":"Middleware that wants to strip hop-by-hop headers (set-cookie, server) from a fetched upstream response before returning it; proxy code that reuses res.headers directly.","solutions":["Copy into a fresh mutable Headers: `const headers = new Headers(res.headers); headers.delete(\"set-cookie\");` then build `new Response(res.body, { status: res.status, headers })`.","Construct `new Response(res.body, res)` and mutate that response's headers (new Response headers have guard \"none\"... \"response\" which allows mutation).","If you only need to read, use res.headers.get() — reads never throw this."],"exampleFix":"// before\nconst res = await fetch(upstream);\nres.headers.delete(\"server\"); // TypeError: immutable\n\n// after\nconst res = await fetch(upstream);\nconst headers = new Headers(res.headers);\nheaders.delete(\"server\");\nreturn new Response(res.body, { status: res.status, headers });","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { res.headers.delete(name); } catch (e) { if (e instanceof TypeError && e.message.includes(\"immutable\")) { /* fall back to copy */ } else throw e; }","preventionTips":["Assume headers of fetch() Responses are read-only in Deno.","Always build a new Headers(res.headers) before mutating anything from the network.","Wrap fetch responses in your own Response at the proxy boundary."],"tags":["http-headers","fetch","immutability","middleware"],"backgroundTag":"immutable-response-headers","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}