{"record":{"id":"820313e829a498b7","repo":"denoland/deno","slug":"invalid-header-name-name","errorCode":null,"errorMessage":"Invalid header name: \"${name}\"","messagePattern":"Invalid header name: \"(.+?)\"","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/20_headers.js","lineNumber":173,"sourceCode":"  HEADER_CACHE_SIZE++;\n  HEADER_NAME_CACHE[name] = valid;\n\n  return valid;\n}\n\n/**\n * https://fetch.spec.whatwg.org/#concept-headers-append\n * @param {Headers} headers\n * @param {string} name\n * @param {string} value\n */\nfunction appendHeader(headers, name, value) {\n  // 1.\n  value = normalizeHeaderValue(value);\n\n  // 2.\n  if (!checkHeaderNameForHttpTokenCodePoint(name)) {\n    throw new TypeError(`Invalid header name: \"${name}\"`);\n  }\n  if (!checkForInvalidValueChars(value)) {\n    throw new TypeError(`Invalid header value: \"${value}\"`);\n  }\n\n  // 3.\n  if (headers[_guard] == \"immutable\") {\n    throw new TypeError(\"Cannot change header: headers are immutable\");\n  }\n\n  // 7.\n  const list = headerListFromHeaders(headers);\n  const lowerNames = ensureLowerNames(headers);\n  const lowercaseName = byteLowerCase(name);\n  for (let i = 0; i < lowerNames.length; i++) {\n    if (lowerNames[i] === lowercaseName) {\n      name = list[i][0];\n      break;","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/20_headers.js#L155-L191","documentation":"appendHeader implements the Fetch spec's 'append a header' algorithm used by the Headers mutation methods (append/set). The name must consist solely of HTTP token code points (validated by HTTP_TOKEN_CODEPOINT_RE with a cache); anything else throws a TypeError showing the offending name.","triggerScenarios":"`h.append(\"Content-Type:\", \"text/html\")` (colon in the name); `h.append(\"a b\", \"v\")` (space); an empty name; non-ASCII names like \"café\"; `h.set(String(arr))` producing a comma-joined name.","commonSituations":"Appending a full header line \"Key: value\" instead of just the key; header names assembled from user/config input; concatenating arrays into a name.","solutions":["Pass only the field name (letters, digits, and !#$%&'*+.^_`|~-) and the value separately","Split 'Key: value' strings on the first ':' before appending","Sanitize dynamic names against the token regex before calling append/set"],"exampleFix":"// before\nheaders.append(\"Content-Type: application/json\", \"\");\n\n// after\nheaders.append(\"Content-Type\", \"application/json\");","handlingStrategy":"type-guard","validationCode":"const HTTP_TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nif (!HTTP_TOKEN_RE.test(name)) {\n  // reject or sanitize before calling headers.append/set\n}","typeGuard":"function isValidHeaderName(name: unknown): name is string {\n  return typeof name === \"string\" && /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name);\n}","tryCatchPattern":null,"preventionTips":["Pass only the field name, never 'Key: value'","Validate dynamic names against the token regex before append/set","Split header lines on the first ':' when importing raw header strings"],"tags":["fetch","headers","validation","web-api"],"backgroundTag":"invalid-header-name","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"}