nodejs/node · error · InvalidArgumentError
${optionName} must contain header names
Error message
${optionName} must contain header names What it means
Thrown by normalizeStripHeaders when the stripHeadersOnRedirect / stripHeadersOnCrossOriginRedirect array contains an element that is not a string. Each entry must be a header-name string; numbers, booleans, objects, null, or undefined elements are rejected.
Source
Thrown at deps/undici/src/lib/handler/redirect-handler.js:191
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)) {
ret.push(headers[i], headers[i + 1])
}
}
} else if (headers && typeof headers === 'object') {
const entries = util.hasSafeIterator(headers) ? headers : Object.entries(headers)
View on GitHub (pinned to 1b2de5e052)
Solutions
- Ensure every element is a string; filter the source list: names.filter(n => typeof n === 'string').
- Build the option only from strongly-typed string arrays at the configuration boundary.
- Default to omitting the option when the filtered list is empty.
Example fix
// before
const strip = ['authorization', traceId ?? undefined]
new Agent({ maxRedirections: 5, stripHeadersOnRedirect: strip })
// after
const strip = ['authorization', traceId].filter(h => typeof h === 'string')
new Agent({ maxRedirections: 5, stripHeadersOnRedirect: strip.length ? strip : undefined }) Defensive patterns
Strategy: type-guard
Validate before calling
function cleanStripHeaders(arr) {
return Array.isArray(arr) ? arr.filter(h => typeof h === 'string') : undefined
} Type guard
function isStringArray(v) { return Array.isArray(v) && v.every(x => typeof x === 'string') } Try / catch
try { new Agent({ stripHeadersOnRedirect: arr }) } catch (e) { if (e.code === 'UND_ERR_INVALID_ARG') { new Agent({ stripHeadersOnRedirect: arr.filter(h => typeof h === 'string') }) } else throw e } Prevention
- Filter non-string entries before assigning header lists.
- Type header arrays as string[] in TypeScript.
- Avoid pushing optional values that may be undefined.
When it happens
Trigger: Passing an array like ['authorization', 42] or ['x-trace', undefined] for stripHeadersOnRedirect / stripHeadersOnCrossOriginRedirect; building the array dynamically without filtering non-strings.
Common situations: Injecting a numeric or boolean config value into a header list; optional header names conditionally pushed as undefined; data sourced from JSON with mixed types.
Related errors
- ${optionName} must be an array
- maxRedirections must be a positive number
- throwOnMaxRedirect must be a boolean
- expected ${name} to be an array or undefined, got ${typeof o
- expected ${name}[${i}] to be a string or RegExp, got ${typeo
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/11d84d69079b5d7b.
Report an issue: GitHub.