{"id":"148539fca645ee96","repo":"aio-libs/aiohttp","slug":"invalid-connection-header","errorCode":null,"errorMessage":"Invalid connection header","messagePattern":"Invalid connection header","errorType":"exception","errorClass":"WSServerHandshakeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":1111,"sourceCode":"                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid response status\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if resp.headers.get(hdrs.UPGRADE, \"\").lower() != \"websocket\":\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid upgrade header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            if not resp._upgraded:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid connection header\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )\n\n            # key calculation\n            r_key = resp.headers.get(hdrs.SEC_WEBSOCKET_ACCEPT, \"\")\n            match = base64.b64encode(hashlib.sha1(sec_key + WS_KEY).digest()).decode()\n            if r_key != match:\n                raise WSServerHandshakeError(\n                    resp.request_info,\n                    resp.history,\n                    message=\"Invalid challenge response\",\n                    status=resp.status,\n                    headers=resp.headers,\n                )","sourceCodeStart":1093,"sourceCodeEnd":1129,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L1093-L1129","documentation":"Raised as `WSServerHandshakeError` (client.py:1110-1117) when `resp._upgraded` is False. `_upgraded` is set internally when the parser sees a `Connection: upgrade` header *and* the underlying transport was actually switched to a raw/passthrough protocol. So status=101 and `Upgrade: websocket` passed, but the connection was not promoted — typically because the `Connection` header is missing/incorrect, or the parser didn't see the upgrade token.","triggerScenarios":"Server returned 101 + Upgrade: websocket but `Connection` header is `keep-alive` or absent; the connection was kept in HTTP mode by an intermediary that didn't fully hand off the socket.","commonSituations":"Proxy sets Upgrade but not Connection header; server framework that 101s without actually detaching the HTTP parser; intermediary (HTTP/2 gateway) that doesn't pass through the connection upgrade.","solutions":["Check `exc.headers.get('Connection')` — it should contain `upgrade`.","Ensure the server/proxy sends `Connection: upgrade` alongside `Upgrade: websocket`.","Connect directly to the WS backend, bypassing any proxy/gateway, to confirm the backend itself upgrades correctly.","Update or reconfigure the intermediary (e.g., nginx needs both `proxy_set_header Upgrade` and `proxy_set_header Connection \"upgrade\"`)."],"exampleFix":"// before\n# nginx only sets Upgrade, not Connection\n// after (nginx)\n# proxy_set_header Upgrade $http_upgrade;\n# proxy_set_header Connection \"upgrade\";","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from aiohttp import WSServerHandshakeError\n\ntry:\n    ws = await session.ws_connect(url)\nexcept WSServerHandshakeError as e:\n    conn = e.headers.get('Connection', '<missing>')\n    if 'connection header' in (e.message or '').lower():\n        log.error('Connection header was: %s', conn)\n    raise","preventionTips":["Server/proxy must send `Connection: upgrade` together with `Upgrade: websocket`.","Verify HTTP/1.1 is used end-to-end (HTTP/2 gateways can break WS upgrade).","Test against the backend directly to isolate intermediary faults."],"tags":["client","websocket","handshake","connection-upgrade","proxy"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}