aio-libs/aiohttp · error · WebSocketError
1009
1009
Error message
Compressed message has too many deflate members
What it means
While decompressing a `permessage-deflate` message, the zlib backend raised `TooManyMembersError` — the deflate stream contains too many dictionary members / expands without bound. This is a DoS guard against zip-bomb payloads; the reader closes the connection with code 1009 (message too big).
Solutions
- If traffic is legitimate, tune compression: negotiate `server_no_context_takeover`/`client_no_context_takeover` to bound decoder state.
- Keep/raise `max_msg_size` appropriately; otherwise treat the 1009 as desired protection and drop the connection.
- Rate-limit or disconnect repeat offenders at the application layer.
Defensive patterns
Strategy: validation
Validate before calling
# bound decoder state and size during handshake/setup ws = await session.ws_connect(url, compress=15, max_msg_size=4 * 1024 * 1024)
Type guard
def is_error(msg) -> bool:
return msg.type == aiohttp.WSMsgType.ERROR Try / catch
msg = await ws.receive()
if msg.type == aiohttp.WSMsgType.ERROR:
exc = msg.data # a WebSocketError
close_code = exc.code # 1002/1007/1009/...
log.warning("ws protocol error %s: %s", close_code, exc) Prevention
- Prefer `*_no_context_takeover` when negotiating deflate with untrusted peers.
- Treat 1009 from compressed messages as a likely zip-bomb; disconnect the peer.
When it happens
Trigger: Peer sends a compressed WS message whose deflate stream is pathological (many members) or expands hugely; a back-end such as isal hits its internal member limit during `decompress_sync`.
Common situations: Malicious client sending a compression bomb; buggy encoder producing a malformed/infinite deflate stream; interop with a peer emitting many deflate blocks.
Related errors
- Compress wbits must between 9 and 15, zlib does not support…
- Extension for deflate not supported
- Invalid window size
- 1009
- Compressed stream has more than
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/0c12668b30b986c1.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/_websocket/reader_c.py:261
if compressed:
if not self._decompressobj:
self._decompressobj = ZLibDecompressor(suppress_deflate_header=True)
# XXX: It's possible that the zlib backend (isal is known to
# do this, maybe others too?) will return max_length bytes,
# but internally buffer more data such that the payload is
# >max_length, so we return one extra byte and if we're able
# to do that, then the message is too big.
try:
payload_merged = self._decompressobj.decompress_sync(
assembled_payload + WS_DEFLATE_TRAILING,
(
self._max_msg_size + 1
if self._max_msg_size
else self._max_msg_size
),
)
except TooManyMembersError as exc:
raise WebSocketError(
WSCloseCode.MESSAGE_TOO_BIG,
"Compressed message has too many deflate members",
) from exc
if self._max_msg_size and len(payload_merged) > self._max_msg_size:
raise WebSocketError(
WSCloseCode.MESSAGE_TOO_BIG,
f"Decompressed message exceeds size limit {self._max_msg_size}",
)
elif type(assembled_payload) is bytes:
payload_merged = assembled_payload
else:
payload_merged = bytes(assembled_payload)
size = len(payload_merged)
if opcode == OP_CODE_TEXT:
if self._decode_text:
try:
text = payload_merged.decode("utf-8")View on GitHub (pinned to d041d4d0fd)