denoland/deno · error · TypeError

Invalid header: length must be 2, but is

Error message

Invalid header: length must be 2, but is ${header.length}

What it means

When a Headers object is initialized from an array (the sequence-of-pairs form), the Fetch spec's fill operation requires every entry to be exactly a [name, value] pair. fillHeaders in ext/fetch/20_headers.js throws this TypeError for any entry whose length is not 2.

Solutions

  1. Ensure every entry is exactly `[name, value]`
  2. Prefer the record form when names are static: `new Headers({ "x": "y" })`
  3. Normalize before constructing: `pairs.map(([k, v]) => [k, v])`

Example fix

// before
const h = new Headers([["content-type", "text/html", "charset=utf-8"]]);

// after
const h = new Headers([["content-type", "text/html; charset=utf-8"]]);
Defensive patterns

Strategy: validation

Validate before calling

function isValidHeaderPairs(init: unknown): boolean {
  return Array.isArray(init) && init.every(
    (e) => Array.isArray(e) && e.length === 2,
  );
}

Type guard

function isHeaderPair(e: unknown): e is [string, string] {
  return Array.isArray(e) && e.length === 2 &&
    typeof e[0] === "string" && typeof e[1] === "string";
}

Prevention

When it happens

Trigger: `new Headers([["a"]])` or `new Headers([["a", "b", "c"]])`; passing such arrays to `new Request(url, { headers })`, `new Response(body, { headers })`, or `fetch(url, { headers })`; entries built from Map.values() where values are 3-element arrays.

Common situations: Header tuples from JSON/config that carry a third element (e.g. a comment); passing [key, value, flag] triples from an internal header model; converting an object-of-objects into nested arrays.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/3896444072d37167. Report an issue: GitHub.

Appendix: source

Thrown at ext/fetch/20_headers.js:103

/**
 * @param {string} potentialValue
 * @returns {string}
 */
function normalizeHeaderValue(potentialValue) {
  return httpTrim(potentialValue);
}

/**
 * @param {Headers} headers
 * @param {HeadersInit} object
 */
function fillHeaders(headers, object) {
  if (ArrayIsArray(object)) {
    for (let i = 0; i < object.length; ++i) {
      const header = object[i];
      if (header.length !== 2) {
        throw new TypeError(
          `Invalid header: length must be 2, but is ${header.length}`,
        );
      }
      appendHeader(headers, header[0], header[1]);
    }
  } else {
    for (const key in object) {
      if (!ObjectHasOwn(object, key)) {
        continue;
      }
      appendHeader(headers, key, object[key]);
    }
  }
}

function checkForInvalidValueChars(value) {
  for (let i = 0; i < value.length; i++) {
    const c = StringPrototypeCharCodeAt(value, i);

View on GitHub (pinned to 9ad36f7a2c)