{"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":"error_code","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_http_outgoing.ts","lineNumber":1327,"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":1309,"sourceCodeEnd":1345,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/_http_outgoing.ts#L1309-L1345","documentation":"validateHeaderValue() throws ERR_HTTP_INVALID_HEADER_VALUE when the value is exactly undefined. Unlike null (which later serializes as a string), an undefined value means 'key present but no value' - almost always a bug such as reading a missing property - so setting it is rejected instead of silently sending garbage.","triggerScenarios":"res.setHeader('x-id', obj.missingProp); writeHead(200, { 'x-tag': undefined }); appendHeader('x-opt', options.feature) where options.feature was never set.","commonSituations":"Optional config fields forwarded straight into headers; destructuring with a typo'd key; JSON payloads where a field is absent rather than null; TypeScript code where a possibly-undefined field slips past checks.","solutions":["Default the value: setHeader('x-id', obj.id ?? '') or skip the header when it is undefined.","Fix the source so the property is actually set, or pass null instead of undefined if an empty-ish header is intended.","Add a filter step when bulk-importing header objects: drop entries whose value === undefined."],"exampleFix":"// before\nres.setHeader('x-request-id', ctx.requestId); // undefined\n\n// after\nif (ctx.requestId !== undefined) res.setHeader('x-request-id', ctx.requestId);","handlingStrategy":"validation","validationCode":"function hasHeaderValue(v) {\n  return v !== undefined;\n}\nfor (const [k, v] of Object.entries(headerObj)) {\n  if (v !== undefined) res.setHeader(k, v); // skip undefined instead of throwing\n}","typeGuard":"type DefinedHeaderRecord = Record<string, string | string[] | null>;\nfunction hasNoUndefinedHeaders(h) {\n  return Object.values(h).every((v) => v !== undefined);\n}","tryCatchPattern":null,"preventionTips":["Filter undefined entries when bulk-importing header objects.","Default optional fields at the source: config.id ?? ''. ","In TypeScript, type header values as string | null to make undefined unrepresentable."],"tags":["http","node-compat","headers","validation"],"backgroundTag":"invalid-http-header","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"}