denoland/deno · error · TypeError
ERR_INVALID_ARG_VALUE
ERR_INVALID_ARG_VALUE
Error message
The 'headers' argument is invalid. Received ${headers} What it means
When headers are supplied as a flat array (e.g. to writeHead(status, headers) or http.request options), _storeHeader expects [name, value, name, value, ...] pairs. An odd-length flat array has an orphan element, so it throws ERR_INVALID_ARG_VALUE for the whole 'headers' argument rather than silently dropping or mispairing a header.
Source
Thrown at ext/node/polyfills/_http_outgoing.ts:956
if (headers) {
if (headers === this[kOutHeaders]) {
// kOutHeaders format: { lowercase: [OriginalName, value] }
// deno-lint-ignore guard-for-in
for (const key in headers) {
const entry = headers[key];
this._storeHeaderEntry(state, entry[0], entry[1], false);
}
} else if (ArrayIsArray(headers)) {
if (headers.length && ArrayIsArray(headers[0])) {
// Array of arrays: [[name, value], ...]
for (let i = 0; i < headers.length; i++) {
const entry = headers[i];
this._storeHeaderEntry(state, entry[0], entry[1], true);
}
} else {
// Flat array: [name, value, name, value, ...]
if (headers.length % 2 !== 0) {
throw new ERR_INVALID_ARG_VALUE("headers", headers);
}
for (let n = 0; n < headers.length; n += 2) {
this._storeHeaderEntry(
state,
headers[n],
headers[n + 1],
true,
);
}
}
} else {
// Plain object: { name: value }
const keys = ObjectKeys(headers);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
this._storeHeaderEntry(state, k, headers[k], true);
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Make the array even-length: every name must be immediately followed by its value.
- Prefer object form writeHead(200, { 'content-type': 'text/html' }) or nested pairs [['content-type','text/html']] which the same code path accepts unambiguously.
- Validate dynamic arrays before passing: assert headers.length % 2 === 0.
Example fix
// before
res.writeHead(200, ['Content-Type', 'text/html', 'X-Extra']); // odd length
// after
res.writeHead(200, { 'Content-Type': 'text/html' });
// or pairs: [['Content-Type', 'text/html'], ['X-Extra', 'value']] Defensive patterns
Strategy: validation
Validate before calling
function toHeaderPairs(headers) {
if (!Array.isArray(headers)) return headers;
if (headers.length % 2 !== 0) {
throw new Error(`headers array must be even-length [name, value, ...]; got ${headers.length}`);
}
return headers;
} Type guard
function isFlatHeaderArray(h) {
return Array.isArray(h) && !(h.length && Array.isArray(h[0]));
}
// even-length flat arrays and [[name, value]] pairs are both accepted by writeHead Prevention
- Prefer object form for static headers: writeHead(200, { 'content-type': 'text/html' }).
- Add a build-time unit test asserting dynamic header arrays have even length.
- Use pairs-of-pairs ([['n','v']]) when names or values may contain commas.
When it happens
Trigger: res.writeHead(200, ['Content-Type', 'text/html', 'X-Extra']) (3 elements); http.request({ headers: ['accept'] }); any code that builds a flat header array dynamically and loses or adds one element.
Common situations: Dynamically constructed header arrays where a push of a name without a value (or a value pushed as two entries) breaks pairing; migrating from object-form headers ({'x': 'y'}) to array-form and missing a member; typos in long header literals.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_HTTP_HEADERS_SENT
- ERR_HTTP_INVALID_HEADER_VALUE
- ERR_PROXY_INVALID_CONFIG
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/435b86db6d5c53d3.
Report an issue: GitHub.