{"id":"0c12668b30b986c1","repo":"aio-libs/aiohttp","slug":"1009","errorCode":"1009","errorMessage":"Decompressed message exceeds size limit {max_msg_size}","messagePattern":"Decompressed message exceeds size limit (.+?)","errorType":"exception","errorClass":"WebSocketError","httpStatus":null,"severity":"warning","filePath":"aiohttp/_websocket/reader_c.py","lineNumber":257,"sourceCode":"            # received.\n            if compressed:\n                if not self._decompressobj:\n                    self._decompressobj = ZLibDecompressor(suppress_deflate_header=True)\n                # XXX: It's possible that the zlib backend (isal is known to\n                # do this, maybe others too?) will return max_length bytes,\n                # but internally buffer more data such that the payload is\n                # >max_length, so we return one extra byte and if we're able\n                # to do that, then the message is too big.\n                payload_merged = self._decompressobj.decompress_sync(\n                    assembled_payload + WS_DEFLATE_TRAILING,\n                    (\n                        self._max_msg_size + 1\n                        if self._max_msg_size\n                        else self._max_msg_size\n                    ),\n                )\n                if self._max_msg_size and len(payload_merged) > self._max_msg_size:\n                    raise WebSocketError(\n                        WSCloseCode.MESSAGE_TOO_BIG,\n                        f\"Decompressed message exceeds size limit {self._max_msg_size}\",\n                    )\n            elif type(assembled_payload) is bytes:\n                payload_merged = assembled_payload\n            else:\n                payload_merged = bytes(assembled_payload)\n\n            size = len(payload_merged)\n            if opcode == OP_CODE_TEXT:\n                if self._decode_text:\n                    try:\n                        text = payload_merged.decode(\"utf-8\")\n                    except UnicodeDecodeError as exc:\n                        raise WebSocketError(\n                            WSCloseCode.INVALID_TEXT, \"Invalid UTF-8 text message\"\n                        ) from exc\n","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/_websocket/reader_c.py#L239-L275","documentation":"WebSocketError (1009 MESSAGE_TOO_BIG) raised after inflating a permessage-deflate message whose decompressed size exceeds self._max_msg_size. The decompressor is allowed one extra byte (max_msg_size+1) precisely so that any result longer than the limit is detectable; this guards against compression bombs. Surfaced in receive() as msg.type == WSMsgType.ERROR with msg.data.code == 1009.","triggerScenarios":"permessage-deflate is negotiated (compress != 0) and a peer sends a small compressed payload that expands past max_msg_size (default 4 MiB). The check at reader_c.py:256 fires after decompress_sync returns more than max_msg_size bytes.","commonSituations":"A legit large compressed message (e.g. a big JSON/image blob) hitting the default 4 MiB cap; a malicious zip-bomb peer; max_msg_size lowered for memory reasons and a routine message now trips it. The connection is torn down with code 1009.","solutions":["Raise the limit if the message is legitimate: WebSocketResponse(max_msg_size=...) / session.ws_connect(url, max_msg_size=...).","Reduce the payload size or page/chunk it on the sender side.","Disable permessage-deflate (compress=0/False) if compression is not needed, removing the decompression-bomb surface.","Treat 1009 in the receive loop as a recoverable 'too big' signal and reconnect/stream instead of receiving whole."],"exampleFix":"# before\nws = await session.ws_connect(url)  # default 4 MiB, big compressed msg -> 1009\n\n# after\nws = await session.ws_connect(url, max_msg_size=16 * 1024 * 1024)","handlingStrategy":"validation","validationCode":"# set the limit BEFORE connecting, sized to your largest legitimate message\nMAX = 16 * 1024 * 1024\nws = await session.ws_connect(url, max_msg_size=MAX)","typeGuard":"from aiohttp import WSMsgType\n\ndef is_message_too_big(msg) -> bool:\n    return msg.type is WSMsgType.ERROR and getattr(msg.data, 'code', None) == 1009","tryCatchPattern":"msg = await ws.receive()\nif msg.type is aiohttp.WSMsgType.ERROR and msg.data.code == 1009:\n    log.info('decompressed message exceeded max_msg_size; reconnecting/streaming')\n    await ws.close()","preventionTips":["Size max_msg_size to your real largest decompressed message, not the default 4 MiB.","Consider disabling permessage-deflate (compress=0) to remove the decompression-bomb surface.","Treat 1009 as recoverable: switch to a chunked/streamed protocol instead of whole-message receives."],"tags":["websocket","compression","size-limit","security","cython","close-1009"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}