aio-libs/aiohttp · error · RuntimeError
The zstd decompression is not available. Please install…
Error message
The zstd decompression is not available. Please install `backports.zstd` module
What it means
Raised by ZSTDDecompressor.__init__ when the zstd backend is missing. On Python < 3.14 aiohttp imports backports.zstd; on 3.14+ it uses the stdlib compression.zstd module. If neither is importable (HAS_ZSTD False) and a Content-Encoding: zstd response arrives, construction of the decompressor fails immediately. The message still names backports.zstd because that is the install path for all current CPython releases.
Solutions
- Install the backend: pip install backports.zstd (or run on Python 3.14+ for the stdlib module).
- Remove 'zstd' from any custom Accept-Encoding header you set on requests.
- If zstd is unavailable, configure the upstream to advertise gzip/identity only.
- Rebuild the deployment image so the optional dep is present in the locked environment.
Example fix
# shell
pip install backports.zstd
# or, in request code, stop forcing zstd
headers={'Accept-Encoding': 'gzip, identity'} Defensive patterns
Strategy: fallback
Validate before calling
try:
from backports.zstd import ZstdDecompressor # noqa: F401
HAS_ZSTD = True
except ImportError:
try:
from compression.zstd import ZstdDecompressor # noqa: F401 # py3.14+
HAS_ZSTD = True
except ImportError:
HAS_ZSTD = False
enc = 'gzip, identity' if not HAS_ZSTD else 'gzip, zstd'
await session.get(url, headers={'Accept-Encoding': enc}) Type guard
null
Try / catch
try:
data = await resp.read()
except RuntimeError as exc:
if 'zstd' in str(exc).lower():
raise RuntimeError('install backports.zstd or drop zstd from Accept-Encoding') from exc
raise Prevention
- Add backports.zstd (or require Python 3.14+) to deployment images.
- Avoid forcing 'zstd' in custom Accept-Encoding unless the backend is present.
- Document the optional decompression deps in the service's setup guide.
When it happens
Trigger: Server returns Content-Encoding: zstd but the optional zstd backend is not installed; Accept-Encoding was forced to include 'zstd' via custom headers; aiohttp upgraded to a version that started advertising zstd without the dep being present in the deployment image.
Common situations: Alpine/slim Docker images without the wheel; pinned old aiohttp in a project whose deployment env never had backports.zstd; server-side negotiation that prefers zstd before gzip.
Related errors
- The brotli decompression is not available. Please install…
- Can not decode content-encoding: zstandard (zstd). Please…
- Compressed stream has more than
- Can not decode content-encoding: brotli (br). Please…
- Can not decode content-encoding
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/88eb119a6a61686e.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/compression_utils.py:485
if hasattr(self._obj, "flush"):
return cast(bytes, self._obj.flush())
return b""
@property
def data_available(self) -> bool:
return not self._obj.is_finished() and not self._last_empty
class ZSTDDecompressor(ConcatDecompressionHandler["ZstdDecompressor"]):
_unlimited = ZSTD_MAX_LENGTH_UNLIMITED
def __init__(
self,
executor: Executor | None = None,
max_sync_chunk_size: int | None = MAX_SYNC_CHUNK_SIZE,
) -> None:
if not HAS_ZSTD:
raise RuntimeError(
"The zstd decompression is not available. "
"Please install `backports.zstd` module"
)
super().__init__(executor=executor, max_sync_chunk_size=max_sync_chunk_size)
self._decompressor = self._new_decompressor()
def _new_decompressor(self) -> "ZstdDecompressor":
return ZstdDecompressor()
def decompress_sync(
self, data: bytes, max_length: int = ZLIB_MAX_LENGTH_UNLIMITED
) -> bytes:
# zstd uses -1 for unlimited, while zlib uses 0 for unlimited
# Convert the zlib convention (0=unlimited) to zstd convention (-1=unlimited)
zstd_max_length = (
ZSTD_MAX_LENGTH_UNLIMITED
if max_length == ZLIB_MAX_LENGTH_UNLIMITED
else max_lengthView on GitHub (pinned to d041d4d0fd)