aio-libs/aiohttp · error · WebSocketError
1009
1009
Error message
Decompressed message exceeds size limit {max_msg_size} What it means
Raised after inflating a compressed (permessage-deflate) WebSocket message when the decompressed byte count exceeds the negotiated _max_msg_size. This is aiohttp's defence against compression-amplification (zip-bomb) attacks; the connection is closed with code 1009 (MESSAGE_TOO_BIG). The reader deliberately decompresses max_msg_size+1 bytes so it can detect overshoot exactly.
Source
Thrown at aiohttp/_websocket/reader_py.py:257
# received.
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.
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
),
)
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")
except UnicodeDecodeError as exc:
raise WebSocketError(
WSCloseCode.INVALID_TEXT, "Invalid UTF-8 text message"
) from exc
View on GitHub (pinned to c0ef574e29)
Solutions
- Raise max_msg_size on WebSocketResponse(...)/ws_connect(...) if larger compressed messages are legitimate.
- Have the peer stream the data in smaller complete (non-fragmented or per-message) frames.
- If unexpected, investigate the peer: a small compressed frame blowing past the limit indicates a zip-bomb attempt.
Example fix
# before ws = WebSocketResponse() # default max_msg_size = 4 MiB # after ws = WebSocketResponse(max_msg_size=16 * 1024 * 1024) # 16 MiB
Defensive patterns
Strategy: validation
Validate before calling
max_msg_size = 16 * 1024 * 1024 # size to fit largest legit compressed message ws = WebSocketResponse(max_msg_size=max_msg_size)
Try / catch
msg = await ws.receive()
if msg.type == aiohttp.WSMsgType.ERROR and ws.exception().code == 1009:
# message too big; log and close
await ws.close() Prevention
- Size max_msg_size to the largest legitimate compressed payload
- Have peers stream large data in smaller messages
When it happens
Trigger: A peer sends a TEXT/BINARY frame with RSV1 set (compress) whose decompressed payload is larger than max_msg_size (default 4 MiB), surfaced in _handle_frame at reader_py.py:257.
Common situations: Peers sending large JSON/log blobs over compressed websockets, malicious payloads, or a too-small max_msg_size set on WebSocketResponse / ws_connect while the server legitimately needs to send big compressed documents.
Related errors
- 1009
- Invalid window size
- Extension for deflate not supported{ext}
- Compress wbits must between 9 and 15, zlib does not support
- 1002
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/322bf17f6f7fb538.json.
Report an issue: GitHub.