denoland/deno · error · TypeError
Invalid header name
Error message
Invalid header name: "${name}" What it means
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.
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
Example fix
// before
headers.append("Content-Type: application/json", "");
// after
headers.append("Content-Type", "application/json"); Defensive patterns
Strategy: type-guard
Validate before calling
const HTTP_TOKEN_RE = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
if (!HTTP_TOKEN_RE.test(name)) {
// reject or sanitize before calling headers.append/set
} Type guard
function isValidHeaderName(name: unknown): name is string {
return typeof name === "string" && /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name);
} Prevention
- 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
When it happens
Trigger: `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.
Common situations: Appending a full header line "Key: value" instead of just the key; header names assembled from user/config input; concatenating arrays into a name.
Related errors
- Invalid header: length must be 2, but is
- Cannot change header: headers are immutable
- Invalid header value
- Body already consumed.
- Cannot read headers: request closed
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/820313e829a498b7.
Report an issue: GitHub.
Appendix: source
Thrown at ext/fetch/20_headers.js:173
HEADER_CACHE_SIZE++;
HEADER_NAME_CACHE[name] = valid;
return valid;
}
/**
* https://fetch.spec.whatwg.org/#concept-headers-append
* @param {Headers} headers
* @param {string} name
* @param {string} value
*/
function appendHeader(headers, name, value) {
// 1.
value = normalizeHeaderValue(value);
// 2.
if (!checkHeaderNameForHttpTokenCodePoint(name)) {
throw new TypeError(`Invalid header name: "${name}"`);
}
if (!checkForInvalidValueChars(value)) {
throw new TypeError(`Invalid header value: "${value}"`);
}
// 3.
if (headers[_guard] == "immutable") {
throw new TypeError("Cannot change header: headers are immutable");
}
// 7.
const list = headerListFromHeaders(headers);
const lowerNames = ensureLowerNames(headers);
const lowercaseName = byteLowerCase(name);
for (let i = 0; i < lowerNames.length; i++) {
if (lowerNames[i] === lowercaseName) {
name = list[i][0];
break;View on GitHub (pinned to 9ad36f7a2c)