{"record":{"id":"f61ad013a4fd1c92","repo":"denoland/deno","slug":"err-http-invalid-header-value","errorCode":"ERR_HTTP_INVALID_HEADER_VALUE","errorMessage":"Invalid value \"${value}\" for header \"${name}\"","messagePattern":"Invalid value \"(.+?)\" for header \"(.+?)\"","errorType":"exception","errorClass":"NodeTypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_http_outgoing.ts","lineNumber":1299,"sourceCode":"      }\n    },\n    \"OutgoingMessage.prototype._headerNames is deprecated\",\n    \"DEP0066\",\n  ),\n});\n\nexport const validateHeaderName = hideStackFrames(\n  (name: string, label?: string): void => {\n    if (typeof name !== \"string\" || !name || !checkIsHttpToken(name)) {\n      throw new ERR_INVALID_HTTP_TOKEN(label || \"Header name\", name);\n    }\n  },\n);\n\nexport const validateHeaderValue = hideStackFrames(\n  (name: string, value: string): void => {\n    if (value === undefined) {\n      throw new ERR_HTTP_INVALID_HEADER_VALUE(value, name);\n    }\n    if (checkInvalidHeaderChar(value)) {\n      debug('Header \"%s\" contains invalid characters', name);\n      throw new ERR_INVALID_CHAR(\"header content\", name);\n    }\n  },\n);\n\nexport function parseUniqueHeadersOption(headers) {\n  if (!ArrayIsArray(headers)) {\n    return null;\n  }\n\n  const unique = new SafeSet();\n  const l = headers.length;\n  for (let i = 0; i < l; i++) {\n    unique.add(StringPrototypeToLowerCase(headers[i]));\n  }","sourceCodeStart":1281,"sourceCodeEnd":1317,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_http_outgoing.ts#L1281-L1317","documentation":"validateHeaderValue() throws ERR_HTTP_INVALID_HEADER_VALUE when the value passed to setHeader()/appendHeader() is exactly `undefined`. The library refuses to serialize a header whose value was never provided.","triggerScenarios":"res.setHeader('X-Trace-Id', undefined) - typically a config lookup or destructuring that returned undefined, or an optional field forwarded straight into a header.","commonSituations":"Optional metadata: `res.setHeader('X-Owner', options.owner)` where owner is sometimes absent; spreading partial objects into header calls; env-driven config where a var is unset.","solutions":["Skip the header when the value is undefined: `if (v !== undefined) res.setHeader(name, v)`","Provide a sensible default: `res.setHeader('X-Owner', v ?? 'unknown')`","Coerce explicitly with String(v) when the value may be a number/boolean"],"exampleFix":"// before\nres.setHeader('X-Owner', options.owner); // options.owner === undefined -> throws\n\n// after\nif (options.owner !== undefined) res.setHeader('X-Owner', options.owner);","handlingStrategy":"validation","validationCode":"// skip headers whose value was never provided\nfor (const [k, v] of Object.entries(headers)) {\n  if (v === undefined) continue;\n  res.setHeader(k, v);\n}","typeGuard":"function hasDefinedHeaderValue(v: unknown): v is string | number | string[] {\n  return v !== undefined;\n}","tryCatchPattern":"try {\n  res.setHeader(name, value);\n} catch (e) {\n  if (e?.code === 'ERR_HTTP_INVALID_HEADER_VALUE' && value === undefined) return;\n  throw e;\n}","preventionTips":["Filter undefined entries out of header maps before applying them","Use `v ?? default` for optional metadata headers","Lint for setHeader(x, maybeUndefined) patterns in strict codebases"],"tags":["http","headers","undefined","validation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}