{"record":{"id":"148539fca645ee96","repo":"aio-libs/aiohttp","slug":"invalid-connection-header","errorCode":null,"errorMessage":"Invalid connection header","messagePattern":"Invalid connection header","errorType":"http","errorClass":"WSServerHandshakeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":1119,"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":1101,"sourceCodeEnd":1137,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client.py#L1101-L1137","documentation":"Raised as WSServerHandshakeError when resp._upgraded is False, i.e. the Connection header did not include 'upgrade' (case-insensitive). Even with status 101 and Upgrade: websocket, the server must also signal Connection: Upgrade to complete RFC 6455.","triggerScenarios":"Server replies 101, Upgrade: websocket, but Connection: close (or no Connection header). resp._upgraded is determined from the Connection header and is False.","commonSituations":"Reverse proxy that strips or rewrites the Connection header. Hand-rolled server that sets Upgrade but forgets Connection. Intermediaries (load balancers, CDNs) rewriting hop-by-hop headers.","solutions":["Inspect the caught WSServerHandshakeError .headers to confirm what Connection value was received.","Fix the server/proxy to send 'Connection: Upgrade'.","Bypass intermediaries that rewrite hop-by-hop headers, or use wss:// end-to-end."],"exampleFix":"// before\n# server returns 101, Upgrade: websocket, but Connection: close\nawait session.ws_connect('wss://x')  # raises Invalid connection header\n// after\n# fix the server to send 'Connection: Upgrade'","handlingStrategy":"try-catch","validationCode":"# Server-side prevention:\n# response_headers['Connection'] = 'Upgrade'\n# response_headers['Upgrade'] = 'websocket'\n# No client-side validation avoids this; the server must comply.","typeGuard":"def connection_includes_upgrade(header_value: str) -> bool:\n    return 'upgrade' in [v.strip().lower() for v in (header_value or '').split(',')]","tryCatchPattern":"from aiohttp import WSServerHandshakeError\n\ntry:\n    ws = await session.ws_connect(url)\nexcept WSServerHandshakeError as e:\n    if e.message == 'Invalid connection header':\n        # check e.headers for Connection; fix server/proxy and retry\n        raise\n    raise","preventionTips":["Confirm the server/proxy preserves hop-by-hop 'Connection: Upgrade'.","Avoid middleboxes that rewrite Connection headers.","In tests, assert both Upgrade and Connection headers are echoed correctly."],"tags":["websocket","handshake","headers"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}