{"record":{"id":"11f4a4a7c14ae1e0","repo":"denoland/deno","slug":"err-http2-header-single-value","errorCode":"ERR_HTTP2_HEADER_SINGLE_VALUE","errorMessage":"Header field \"${key}\" must only have a single value","messagePattern":"Header field \"(.+?)\" must only have a single value","errorType":"validation","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/http2/util.ts","lineNumber":843,"sourceCode":"    (v) => StringPrototypeToLowerCase(v),\n  );\n\n  function processHeader(key, value) {\n    key = StringPrototypeToLowerCase(key);\n    const isSingleValueHeader = strictSingleValueFields &&\n      kSingleValueHeaders.has(key);\n    let isArray = ArrayIsArray(value);\n    if (isArray) {\n      switch (value.length) {\n        case 0:\n          return;\n        case 1:\n          value = String(value[0]);\n          isArray = false;\n          break;\n        default:\n          if (isSingleValueHeader) {\n            throw new ERR_HTTP2_HEADER_SINGLE_VALUE(key);\n          }\n      }\n    } else {\n      value = String(value);\n    }\n    if (isSingleValueHeader) {\n      if (singles.has(key)) {\n        throw new ERR_HTTP2_HEADER_SINGLE_VALUE(key);\n      }\n      singles.add(key);\n    }\n    const flags = ArrayPrototypeIncludes(neverIndex, key)\n      ? kNeverIndexFlag\n      : kNoHeaderFlags;\n    if (key[0] === \":\") {\n      const err = assertValuePseudoHeader(key);\n      if (err !== undefined) {\n        throw err;","sourceCodeStart":825,"sourceCodeEnd":861,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/http2/util.ts#L825-L861","documentation":"Some HTTP/2 header fields are single-valued by spec (kSingleValueHeaders, util.ts:131 — the pseudo-headers plus content-length, authorization, age, content-encoding/language/location/length, etc.). If such a key arrives with an ARRAY value of length > 1, buildNgHeaderString throws ERR_HTTP2_HEADER_SINGLE_VALUE (util.ts:843) — the value cannot be joined or repeated.","triggerScenarios":"Passing headers like { 'content-length': ['42','43'] } or an array pair ['authorization', ['a','b']] to http2session.request()/stream.respond(); arrays of length 0 are skipped and length 1 is unwrapped, only length >= 2 with a single-value key throws here.","commonSituations":"Merging header sets where one side already had an array (set-cookie is multi-valued and fine, but people over-generalize); query-string parsers producing arrays for repeated params reused as headers; middleware that normalizes every header value into [value].","solutions":["Ensure single-value headers always end up as one scalar string before calling request()/respond(): collapse arrays of length 1 and reject/resolve longer ones.","If two values exist, decide which one is authoritative (e.g. take the first, or fail with your own error) instead of passing both.","Keep a deny-list check for kSingleValueHeaders-style fields when merging header objects."],"exampleFix":"// before\nstream.respond({ ':status': 200, 'content-length': ['10', '20'] });\n\n// after\nstream.respond({ ':status': 200, 'content-length': '10' });","handlingStrategy":"validation","validationCode":"const SINGLE = new Set([':status', ':method', ':authority', ':scheme', ':path', ':protocol', 'content-length', 'authorization', 'age', 'content-encoding', 'content-language', 'content-location']);\nfor (const [k, v] of Object.entries(headers)) {\n  if (SINGLE.has(k.toLowerCase()) && Array.isArray(v)) {\n    if (v.length > 1) throw new Error(`${k} must be single-valued`);\n    headers[k] = v[0];\n  }\n}","typeGuard":"const isSingleValueHeader = (k: string) => SINGLE.has(k.toLowerCase());","tryCatchPattern":null,"preventionTips":["Only set-cookie/via style fields may repeat","Collapse length-1 arrays to scalars before request()/respond()"],"tags":["http2","headers","node-compat"],"backgroundTag":"duplicate-header-value","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}