aio-libs/aiohttp · error · WSHandshakeError

Invalid window size

Error message

Invalid window size

What it means

During the WebSocket handshake the *client* parses the server's `Sec-WebSocket-Extensions` response. For `permessage-deflate`, the `client_max_window_bits` value must be between 9 and 15 because zlib cannot operate with a window bit of 8. An out-of-range value raises `WSHandshakeError`, which aiohttp's client re-raises as `WSServerHandshakeError` (see `client.py:1159`).

Solutions

  1. Disable compression on the client to bypass negotiation entirely: `ws_connect(url, compress=0)` (or omit `compress`).
  2. Fix the server to send a valid `client_max_window_bits` (9-15) or omit the value.
  3. Catch `WSServerHandshakeError` and retry without compression as a fallback.

Example fix

# before
ws = await session.ws_connect(url, compress=15)  # server sent client_max_window_bits=8 -> error
# after
try:
    ws = await session.ws_connect(url, compress=15)
except aiohttp.WSServerHandshakeError:
    ws = await session.ws_connect(url, compress=0)  # fall back to uncompressed
Defensive patterns

Strategy: fallback

Try / catch

try:
    ws = await session.ws_connect(url, compress=15)
except aiohttp.WSServerHandshakeError as exc:
    # server returned an unacceptable permessage-deflate extension
    ws = await session.ws_connect(url, compress=0)

Prevention

When it happens

Trigger: Calling `session.ws_connect(url, compress=15)` (or any truthy `compress`) against a server whose `Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits=N` has N < 9 or N > 15. Internally `ws_ext_parse(hdr, isserver=False)` raises at `helpers.py:117`.

Common situations: Interoperating with a buggy/non-conformant server that echoes an invalid window size; a custom server confusing zlib's general wbits (which allows 8 in some modes) with the WS deflate range; a proxy rewriting the header.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/d12a94b0d124567a. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/_websocket/helpers.py:117

                    # Compress wbit 8 does not support in zlib
                    # If compress level not support,
                    # CONTINUE to next extension
                    if compress > 15 or compress < 9:
                        compress = 0
                        continue
                if match.group(1):
                    notakeover = True
                # Ignore regex group 5 & 6 for client_max_window_bits
                break
            else:
                if match.group(6):
                    compress = int(match.group(6))
                    # Group5 must match if group6 matches
                    # Compress wbit 8 does not support in zlib
                    # If compress level not support,
                    # FAIL the parse progress
                    if compress > 15 or compress < 9:
                        raise WSHandshakeError("Invalid window size")
                if match.group(2):
                    notakeover = True
                # Ignore regex group 5 & 6 for client_max_window_bits
                break
        # Return Fail if client side and not match
        elif not isserver:
            raise WSHandshakeError("Extension for deflate not supported" + ext.group(1))

    return compress, notakeover


def ws_ext_gen(
    compress: int = 15, isserver: bool = False, server_notakeover: bool = False
) -> str:
    # client_notakeover=False not used for server
    # compress wbit 8 does not support in zlib
    if compress < 9 or compress > 15:
        raise ValueError(

View on GitHub (pinned to d041d4d0fd)