nodejs/node · error · InvalidArgumentError

${optionName} must be an array

Error message

${optionName} must be an array

What it means

Thrown by normalizeStripHeaders when the stripHeadersOnRedirect or stripHeadersOnCrossOriginRedirect option is present but is not an array. These options let you list extra header names to drop when following a redirect (same-origin) or when the redirect crosses origins. Both must be arrays of header-name strings (or null/undefined to leave them unset).

Source

Thrown at deps/undici/src/lib/handler/redirect-handler.js:185

    return true
  }
  if (removeContent && name.startsWith('content-')) {
    return true
  }
  if (unknownOrigin) {
    return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
  }
  return false
}

// https://tools.ietf.org/html/rfc7231#section-6.4
function normalizeStripHeaders (headers, optionName) {
  if (headers == null) {
    return null
  }

  if (!Array.isArray(headers)) {
    throw new InvalidArgumentError(`${optionName} must be an array`)
  }

  const normalized = new Set()
  for (const header of headers) {
    if (typeof header !== 'string') {
      throw new InvalidArgumentError(`${optionName} must contain header names`)
    }

    normalized.add(util.headerNameToString(header))
  }
  return normalized
}

function cleanRequestHeaders (headers, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin) {
  const ret = []
  if (Array.isArray(headers)) {
    for (let i = 0; i < headers.length; i += 2) {
      if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin)) {

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Pass header names as an array of strings: ['authorization', 'x-api-key'].
  2. If you have a Set or comma-separated string, convert first: Array.from(set) or str.split(',').
  3. Omit the option when you only want the default Host/Content-* stripping behavior.

Example fix

// before
new Agent({ maxRedirections: 5, stripHeadersOnRedirect: 'authorization,cookie' })

// after
new Agent({ maxRedirections: 5, stripHeadersOnRedirect: ['authorization', 'cookie'] })
Defensive patterns

Strategy: validation

Validate before calling

function normalizeStripHeaders(v) {
  if (v == null) return undefined
  if (!Array.isArray(v)) return [String(v)]
  return v.filter(h => typeof h === 'string')
}

Type guard

function isStripHeaders(v) { return v == null || (Array.isArray(v) && v.every(h => typeof h === 'string')) }

Try / catch

try { new Agent({ maxRedirections: 5, stripHeadersOnRedirect: list }) } catch (e) { if (e.code === 'UND_ERR_INVALID_ARG') { new Agent({ maxRedirections: 5, stripHeadersOnRedirect: Array.isArray(list) ? list : [list].filter(String) }) } else throw e }

Prevention

When it happens

Trigger: Passing stripHeadersOnRedirect / stripHeadersOnCrossOriginRedirect as a string (e.g. 'authorization'), a Set, an object, or a comma-separated list instead of an array, in Agent/Pool/Client opts or per-request opts.

Common situations: Migrating from a config format that used a single string or a Set; copying header-list config from another library that accepts different shapes; TypeScript where the type was loosened.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/97e8a7e8dcc3cab4. Report an issue: GitHub.