nodejs/node · error · Error
too many content-encodings in response: ${parts.length}, max
Error message
too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings} What it means
Thrown by the decompress() interceptor's #createDecompressionChain when the response Content-Encoding header contains more than 5 comma-separated encodings. This is a deliberate resource-exhaustion guard mirroring fixes for urllib3 GHSA-gm62-xv2j-4w53 and curl CVE-2022-32206: deeply nested encodings can be used to amplify a small response into huge CPU/memory use, so the interceptor caps the chain length at 5.
Source
Thrown at deps/undici/src/lib/interceptor/decompress.js:75
if (this.#skipErrorResponses && statusCode >= 400) return true
return false
}
/**
* Creates a chain of decompressors for multiple content encodings
*
* @param {string} encodings - Comma-separated list of content encodings
* @returns {Array<DecompressorStream>} - Array of decompressor streams
* @throws {Error} - If the number of content-encodings exceeds the maximum allowed
*/
#createDecompressionChain (encodings) {
const parts = encodings.split(',')
// Limit the number of content-encodings to prevent resource exhaustion.
// CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
const maxContentEncodings = 5
if (parts.length > maxContentEncodings) {
throw new Error(`too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings}`)
}
/** @type {DecompressorStream[]} */
const decompressors = []
for (let i = parts.length - 1; i >= 0; i--) {
const encoding = parts[i].trim()
if (!encoding) continue
if (!supportedEncodings[encoding]) {
decompressors.length = 0 // Clear if unsupported encoding
return decompressors // Unsupported encoding
}
decompressors.push(supportedEncodings[encoding]())
}
return decompressorsView on GitHub (pinned to 1b2de5e052)
Solutions
- Treat the response as untrusted: do not use the decompress interceptor for that origin, or fix the origin to send a single sane encoding.
- If you control the server, ensure Content-Encoding has at most one (or a small, valid) layer.
- Catch the error per-request and fall back to consuming the raw (still-encoded) body or failing the request explicitly.
Example fix
// before
client.compose(interceptors.decompress())
// a response with Content-Encoding: gzip, gzip, gzip, gzip, gzip, gzip throws
// after
// exclude the offending origin from decompression, or handle the error:
try {
await client.request(opts)
} catch (e) {
if (e.message.startsWith('too many content-encodings')) {
// consume raw body or reject the response
throw new Error('Refusing suspicious response from ' + opts.origin)
}
throw e
} Defensive patterns
Strategy: try-catch
Try / catch
try { await client.request(opts) } catch (e) { if (e.message.startsWith('too many content-encodings')) { throw new Error(`Refusing suspicious response from ${opts.origin}`) } else throw e } Prevention
- Do not enable the decompress interceptor for untrusted origins.
- Ensure your origin sends at most one Content-Encoding layer.
- Treat deeply nested encodings as an attack signal.
When it happens
Trigger: A server (often malicious or misconfigured) returns a Content-Encoding header like 'gzip, gzip, gzip, gzip, gzip, gzip' (>5 entries). The decompress interceptor throws synchronously while setting up the decompression pipeline.
Common situations: Security testing/fuzzing; buggy compression middleware that stacks encodings; adversarial origins; intermediary that appends encodings on each hop.
Related errors
- UND_ERR_INVALID_ARG
- UND_ERR_INVALID_ARG
- Proxy-Authorization should be sent in ProxyAgent constructor
- maxRedirections must be a positive number
- throwOnMaxRedirect must be a boolean
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/73b0fdbb2ff44098.
Report an issue: GitHub.