{"record":{"id":"820313e829a498b7","repo":"denoland/deno","slug":"invalid-header-name-name","errorCode":null,"errorMessage":"Invalid header name: \"${name}\"","messagePattern":"Invalid header name: \"(.+?)\"","errorType":"validation","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/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/20_headers.js#L155-L191","documentation":"appendHeader implements the spec's header append: after normalizing the value it validates the name against HTTP token code points (checkHeaderNameForHttpTokenCodePoint). Names containing spaces, ':', empty strings, or non-ASCII characters are rejected.","triggerScenarios":"headers.set('Content Type', v); headers.append('a:b', v); headers.set('', v); any name with characters outside !#$%&'*+-.^_`|~0-9A-Za-z.","commonSituations":"User or config data used as header names; template strings that introduce whitespace; non-ASCII (i18n) text in names.","solutions":["Use registered names with hyphens: 'Content-Type'.","Validate names against the token regex /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ before set/append.","Never put free text into header names — only into values."],"exampleFix":"// before\nheaders.set('X-Custom Name', 'v');\n// after\nheaders.set('X-Custom-Name', 'v');","handlingStrategy":"type-guard","validationCode":"const tokenRe = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;\nif (!tokenRe.test(name)) {\n  throw new Error(`illegal header name: ${JSON.stringify(name)}`);\n}\nheaders.set(name, value);","typeGuard":"function isValidHeaderName(name: string): boolean {\n  return /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name);\n}","tryCatchPattern":"try {\n  headers.set(name, value);\n} catch (e) {\n  if (e instanceof TypeError && /Invalid header name/.test(e.message)) {\n    // skip or normalize the header, log the offending name\n  } else {\n    throw e;\n  }\n}","preventionTips":["Treat header names as code, not data: keep them as constants.","If names are dynamic, validate against the token regex at the boundary where they enter the system."],"tags":["headers","fetch","http","validation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}