aio-libs/aiohttp · error · WSHandshakeError

Extension for deflate not supported{ext}

Error message

Extension for deflate not supported{ext}

What it means

WSHandshakeError raised by ws_ext_parse() on the CLIENT side when the server's Sec-WebSocket-Extensions response contains a permessage-deflate entry whose parameters do not match the expected grammar in _WS_EXT_RE. aiohttp only understands server_no_context_takeover, client_no_context_takeover, server_max_window_bits and client_max_window_bits; anything else is treated as an unsupported extension and fails the handshake.

Source

Thrown at aiohttp/_websocket/helpers.py:124

                    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(
            "Compress wbits must between 9 and 15, zlib does not support wbits=8"
        )
    enabledext = ["permessage-deflate"]
    if not isserver:
        enabledext.append("client_max_window_bits")

    if compress < 15:

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Disable compression on the client to avoid parsing the extension: await session.ws_connect(url, compress=0).
  2. Catch WSHandshakeError around ws_connect and retry without compression.
  3. Inspect the server's raw Sec-WebSocket-Extensions header and remove/reconfigure the offending parameter on the server side.
  4. If you control the server, only emit the four RFC-7692 parameters aiohttp understands.

Example fix

# before
ws = await session.ws_connect(url)  # WSHandshakeError: Extension for deflate not supported; foo=bar

# after
ws = await session.ws_connect(url, 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 sent an unsupported deflate extension param; go uncompressed
    ws = await session.ws_connect(url, compress=0)

Prevention

When it happens

Trigger: The server returns 'Sec-WebSocket-Extensions: permessage-deflate; foo=bar' (or any unrecognized/ill-formed parameter suffix). The regex _WS_EXT_RE.match(defext) returns None, the code reaches the 'elif not isserver' branch, and raises with the offending suffix appended.

Common situations: A server or reverse proxy injects a non-standard deflate parameter; an intermediary (nginx with a custom module, a WAF) rewrites the extension header; interoperating with a library that uses experimental deflate extensions aiohttp does not implement.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/0f0289b48a47cfb6.json. Report an issue: GitHub.