jsdom/jsdom · error · Error

too many content-encodings in response: ${parts.length}, max

Error message

too many content-encodings in response: ${parts.length}, max is ${maxContentEncodings}

What it means

The decompress interceptor rejects responses whose `Content-Encoding` header lists more than 5 comma-separated encodings. Each encoding requires a decompression step in a chain, and jsdom caps the chain at `maxContentEncodings = 5` to bound resource use and guard against pathological or malicious responses. Exceeding the cap throws a plain Error naming the count and the maximum.

Source

Thrown at lib/jsdom/browser/resources/decompress-interceptor.js:54

  #shouldSkipDecompression(contentEncoding, statusCode) {
    if (!contentEncoding || statusCode < 200) {
      return true;
    }
    if (this.#skipStatusCodes.includes(statusCode)) {
      return true;
    }
    if (this.#skipErrorResponses && statusCode >= 400) {
      return true;
    }
    return false;
  }

  #createDecompressionChain(encodings) {
    const parts = encodings.split(",");

    const maxContentEncodings = 5;
    if (parts.length > maxContentEncodings) {
      throw new Error(`too many content-encodings in response: ${parts.length}, max is ${maxContentEncodings}`);
    }

    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;
        return decompressors;
      }

      decompressors.push(supportedEncodings[encoding]());
    }

View on GitHub (pinned to 904cc9cd24)

Solutions

  1. Fix the server/proxy so it sends a single Content-Encoding value (e.g. `gzip`)
  2. Check for double-compression in middleware: the body should be compressed once, not per-hop
  3. If you legitimately need deep stacking, raise `maxContentEncodings` in decompress-interceptor.js and reinstall as a patch
  4. Use undici interceptors to strip duplicate encodings before jsdom's interceptor runs

Example fix

// before (server response)
Content-Encoding: gzip, deflate, gzip, br, gzip, deflate
// after
Content-Encoding: gzip
Defensive patterns

Strategy: validation

Validate before calling

function hasSafeContentEncoding(headers, max = 5) {
  const ce = headers.get('content-encoding') || '';
  return ce.split(',').filter(Boolean).length <= max;
}

Try / catch

try {
  await loadResource(url);
} catch (e) {
  if (e.message.startsWith('too many content-encodings')) {
    console.error('Server over-compressed response; fix Content-Encoding header', e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: A server (or intercepted mock) responds with `Content-Encoding: gzip, gzip, gzip, gzip, gzip, gzip` (six or more encodings). The error is thrown from #createDecompressionChain while building the decompressor chain for the response.

Common situations: Misconfigured compression middleware that compresses multiple times; proxies stacking encodings; deliberately malicious or fuzzed servers; mocked responses in tests with hand-written Content-Encoding headers.

Related errors


AI-assisted analysis of jsdom/jsdom@904cc9cd24 (2026-09-01). Data as JSON: /api/errors/007131edfeae162e. Report an issue: GitHub.