{"id":"e467c089f5f61da8","repo":"aio-libs/aiohttp","slug":"invalid-upgrade-header","errorCode":null,"errorMessage":"Invalid upgrade header","messagePattern":"Invalid upgrade header","errorType":"exception","errorClass":"WSServerHandshakeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":1102,"sourceCode":"            proxy=proxy,\n            ssl=ssl,\n            server_hostname=server_hostname,\n            proxy_headers=proxy_headers,\n        )\n\n        try:\n            # check handshake\n            if resp.status != 101:\n                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, \"\")","sourceCodeStart":1084,"sourceCodeEnd":1120,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L1084-L1120","documentation":"Raised as `WSServerHandshakeError` (client.py:1101-1108) when the response to a WS upgrade request has an `Upgrade` header whose value (case-insensitive) is not exactly `websocket`. RFC 6455 requires the server to echo `Upgrade: websocket`; a mismatch means the server did not honour the upgrade (e.g., returned a normal HTTP response). Status was 101 but the Upgrade header is wrong/absent.","triggerScenarios":"Server returned 101 but with `Upgrade: h2c` or no Upgrade header; intermediary rewrote the Upgrade header; buggy server that sends 101 for non-WS reasons.","commonSituations":"Reverse proxy or CDN that returns 101 but strips/alters the Upgrade header; load balancer doing protocol negotiation; misconfigured server framework that doesn't fully implement RFC 6455.","solutions":["Inspect `exc.headers` to see the actual Upgrade header value.","Fix the server/proxy to echo `Upgrade: websocket` on 101 responses.","Bypass intermediaries (connect directly to the WS server) to isolate where the header is dropped.","If the server genuinely doesn't support WS, switch to a real WS endpoint."],"exampleFix":"// before\n# nginx missing: proxy_set_header Upgrade $http_upgrade;\nawait session.ws_connect('wss://host/ws')\n// after (server-side nginx fix)\n# proxy_http_version 1.1;\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    upg = e.headers.get('Upgrade', '<missing>')\n    if 'invalid upgrade header' in (e.message or '').lower():\n        log.error('Upgrade header was: %s', upg)\n    raise","preventionTips":["Ensure the server/proxy echoes `Upgrade: websocket` on 101.","Configure nginx with the Upgrade forwarding directives.","Bypass the proxy to confirm the backend itself upgrades correctly."],"tags":["client","websocket","handshake","headers","proxy"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}