aio-libs/aiohttp · error · RuntimeError

The brotli decompression is not available. Please install `B

Error message

The brotli decompression is not available. Please install `Brotli` module

What it means

Raised when constructing BrotliDecompressor while the optional `Brotli` (or `brotlipy`) package is not importable - aiohttp sets HAS_BROTLI=False at import time. The decompressor is only built when a response arrives with `Content-Encoding: br`, so this RuntimeError fires at response-body read time rather than at import. aiohttp refuses to silently mis-serve compressed bytes; it asks you to install the missing codec.

Source

Thrown at aiohttp/compression_utils.py:350

        )

    @property
    def eof(self) -> bool:
        return self._decompressor.eof


class BrotliDecompressor(DecompressionBaseHandler):
    # Supports both 'brotlipy' and 'Brotli' packages
    # since they share an import name. The top branches
    # are for 'brotlipy' and bottom branches for 'Brotli'
    def __init__(
        self,
        executor: Executor | None = None,
        max_sync_chunk_size: int | None = MAX_SYNC_CHUNK_SIZE,
    ) -> None:
        """Decompress data using the Brotli library."""
        if not HAS_BROTLI:
            raise RuntimeError(
                "The brotli decompression is not available. "
                "Please install `Brotli` module"
            )
        self._obj = brotli.Decompressor()
        self._last_empty = False
        super().__init__(executor=executor, max_sync_chunk_size=max_sync_chunk_size)

    def decompress_sync(
        self, data: Buffer, max_length: int = ZLIB_MAX_LENGTH_UNLIMITED
    ) -> bytes:
        """Decompress the given data."""
        if hasattr(self._obj, "decompress"):
            if max_length == ZLIB_MAX_LENGTH_UNLIMITED:
                result = cast(bytes, self._obj.decompress(data))
            else:
                result = cast(bytes, self._obj.decompress(data, max_length))
        else:
            if max_length == ZLIB_MAX_LENGTH_UNLIMITED:

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Install the codec: `pip install Brotli` (or add `aiohttp[brotli]` to requirements).
  2. If you cannot install it, strip brotli from Accept-Encoding via `headers={'Accept-Encoding': 'gzip, deflate'}` so the server never returns br.
  3. Pin Brotli in your deployment manifest so it survives image rebuilds.

Example fix

# before
# Brotli not installed -> RuntimeError on resp.read()
# after
# requirements.txt
Brotli>=1.0.9
Defensive patterns

Strategy: validation

Validate before calling

def brotli_available() -> bool:
    try:
        import brotli  # noqa: F401
        return True
    except ImportError:
        return False

# before issuing requests, or set Accept-Encoding to exclude 'br' if False

Try / catch

try:
    body = await resp.read()
except RuntimeError as e:
    if 'brotli' in str(e).lower():
        # retry without brotli in Accept-Encoding
        ...
    raise

Prevention

When it happens

Trigger: Server returns `Content-Encoding: br` (brotli) but the `Brotli` package is not installed in the environment, then `await resp.read()`/`resp.text()` triggers BrotliDecompressor construction.

Common situations: Fresh deploy of aiohttp without brotli extra. Slim Docker images that stripped optional deps. Server-side enablement of brotli without coordinating with the client dependency list. aiohttp[speedups]/brotli extra not in requirements.

Related errors


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