aio-libs/aiohttp · error · WSHandshakeError
Invalid window size
Error message
Invalid window size
What it means
WSHandshakeError raised by ws_ext_parse() during the CLIENT side (isserver=False) of the permessage-deflate negotiation when the server's Sec-WebSocket-Extensions response advertises a client_max_window_bits value outside the valid 9-15 range. zlib cannot use wbits=8 and values above 15 are illegal, so aiohttp rejects the handshake rather than accepting a broken compression agreement. It is a hard handshake failure, not a warning.
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 c0ef574e29)
Solutions
- Disable compression on the client to bypass the broken negotiation: await session.ws_connect(url, compress=0).
- Wrap ws_connect in try/except WSHandshakeError and fall back to a non-compressed connection (retry with compress=0).
- Fix the server/gateway so client_max_window_bits, if echoed, is in the 9-15 range or omitted entirely.
- Report the non-compliant Sec-WebSocket-Extensions header to the server maintainer; capture the raw header to confirm the offending value.
Example fix
# before
ws = await session.ws_connect('wss://buggy.example/feed') # WSHandshakeError: Invalid window size
# after
try:
ws = await session.ws_connect('wss://buggy.example/feed')
except aiohttp.WSHandshakeError:
ws = await session.ws_connect('wss://buggy.example/feed', compress=0) Defensive patterns
Strategy: try-catch
Try / catch
from aiohttp import WSHandshakeError
try:
ws = await session.ws_connect(url)
except WSHandshakeError as exc:
# server advertised an invalid client_max_window_bits; retry uncompressed
ws = await session.ws_connect(url, compress=0) Prevention
- Catch WSHandshakeError around every ws_connect that leaves compression at the default.
- Have a compress=0 fallback ready for servers with broken deflate negotiation.
- Log the raw Sec-WebSocket-Extensions response header when a handshake fails to confirm the cause.
When it happens
Trigger: The server returns a header like 'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits=8' (or 16, or any value <9 or >15) and the client called session.ws_connect(url) with compression enabled (compress=15 default). ws_ext_parse parses group(6) from _WS_EXT_RE, sees the out-of-range value, and raises.
Common situations: Talking to a buggy/non-RFC-7692 server or gateway that mangles the deflate extension params; a custom server echoing back the client's offered window bits incorrectly; testing against a mock server that hard-codes an invalid wbits. The error appears at await session.ws_connect(...) time.
Related errors
- Extension for deflate not supported{ext}
- Compress wbits must between 9 and 15, zlib does not support
- Invalid response status
- Invalid upgrade header
- Invalid connection header
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/d12a94b0d124567a.json.
Report an issue: GitHub.