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
- Install the codec: `pip install Brotli` (or add `aiohttp[brotli]` to requirements).
- If you cannot install it, strip brotli from Accept-Encoding via `headers={'Accept-Encoding': 'gzip, deflate'}` so the server never returns br.
- 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
- Add `Brotli` (or `aiohttp[brotli]`) to your deployment requirements.
- In slim images, run `pip check` in CI to confirm optional deps are present.
- Restrict Accept-Encoding to codecs you can decode if you cannot guarantee the dep.
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
- The zstd decompression is not available. Please install `bac
- Can not decode content-encoding: brotli (br). Please install
- Can not decode content-encoding: zstandard (zstd). Please in
- Can not decode content-encoding: %s
- deflate
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/dfa061a4b894bbda.json.
Report an issue: GitHub.