aio-libs/aiohttp · error · ContentEncodingError

Can not decode content-encoding: %s

Error message

Can not decode content-encoding: %s

What it means

Generic ContentEncodingError raised when the underlying decompressor (zlib/brotli/zstd) raises during decompress_sync — i.e. the compressed body is corrupt, truncated, or uses an unexpected format. The encoding name is interpolated into the message.

Source

Thrown at aiohttp/http_parser.py:1189

            # RFC1950
            # bits 0..3 = CM = 0b1000 = 8 = "deflate"
            # bits 4..7 = CINFO = 1..7 = windows size.
            if self.encoding == "deflate" and chunk[0] & 0xF != 8:
                # Change the decoder to decompress incorrectly compressed data
                # Actually we should issue a warning about non-RFC-compliant data.
                self.decompressor = ZLibDecompressor(
                    encoding=self.encoding, suppress_deflate_header=True
                )
            self._started_decoding = True

        low_water = self.out._low_water
        max_length = (
            0 if low_water >= sys.maxsize else max(self._max_decompress_size, low_water)
        )
        try:
            chunk = self.decompressor.decompress_sync(chunk, max_length=max_length)
        except Exception:
            raise ContentEncodingError(
                "Can not decode content-encoding: %s" % self.encoding
            )

        if chunk:
            self.out.feed_data(chunk)
        return self.decompressor.data_available

    def feed_eof(self) -> None:
        chunk = self.decompressor.flush()
        # This should never contain data as we defer the call until exhausting
        # the decompression. If .flush() is returning data, this may indicate a
        # zip bomb vulnerability as it will decompress all remaining data at once.
        assert not chunk

        if self.size > 0:
            # decompressor is not brotli unless encoding is "br"
            if self.encoding == "deflate" and not self.decompressor.eof:  # type: ignore[union-attr]
                raise ContentEncodingError("deflate")

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Verify the body is actually encoded as advertised (curl --compressed -o /tmp/x and inspect).
  2. Check for a proxy/CDN re-compressing or stripping encoding.
  3. Retry; if stable, report to the upstream.
  4. As a workaround, request no compression (Accept-Encoding: identity) or set auto_decompress=False.

Example fix

// before
#   body = await resp.read()  # zlib.error on corrupt gzip

# after - request identity or stream raw
headers = {'Accept-Encoding': 'identity'}
resp = await session.get(url, headers=headers)
# or disable auto-decompress and handle manually
session = aiohttp.ClientSession(auto_decompress=False)
Defensive patterns

Strategy: fallback

Try / catch

from aiohttp.http_exceptions import ContentEncodingError
try:
    body = await resp.read()
except ContentEncodingError:
    # retry without compression
    async with session.get(url, headers={'Accept-Encoding': 'identity'}) as r:
        body = await r.read()

Prevention

When it happens

Trigger: DeflateBuffer.feed_data calls self.decompressor.decompress_sync(chunk) which raises (zlib.error, brotli error, zstd error); the exception is caught and re-raised as ContentEncodingError with the encoding. Happens on corrupt gzip/deflate/br/zstd payloads.

Common situations: Corrupt downloads; compression applied twice; Content-Encoding mismatch (server says gzip but sends raw); truncated compressed stream; intermediary altering the body.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/dff2f9c814d57b10.json. Report an issue: GitHub.