{"id":"12f47db00eeee1fa","repo":"aio-libs/aiohttp","slug":"invalid-response-status","errorCode":null,"errorMessage":"Invalid response status","messagePattern":"Invalid response status","errorType":"exception","errorClass":"WSServerHandshakeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":1093,"sourceCode":"            )\n\n        # send request\n        resp = await self.request(\n            method,\n            url,\n            params=params,\n            headers=real_headers,\n            read_until_eof=False,\n            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(","sourceCodeStart":1075,"sourceCodeEnd":1111,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L1075-L1111","documentation":"Raised as `WSServerHandshakeError` (client.py:1090-1099) during `ws_connect` when the server's response status code is not `101 Switching Protocols`. A successful WebSocket opening handshake must return 101; anything else (200, 301, 401, 403, 404, 500, etc.) means the upgrade was refused or short-circuited. The exception carries `request_info`, `history`, `status`, and `headers` for diagnosis.","triggerScenarios":"Hitting an endpoint that isn't a WebSocket server (e.g., plain HTTP); server requires auth and returns 401; proxy/load-balancer returns 200 for an HTML error page; URL uses `http://` instead of `wss://`; server doesn't have WS enabled on that route.","commonSituations":"Wrong scheme (`http` vs `ws`, `https` vs `wss`); hitting a REST endpoint instead of the WS endpoint; TLS termination proxy stripping Upgrade headers; reverse proxy (nginx) not configured with `proxy_set_header Upgrade $http_upgrade`; auth/cookie missing so server returns 401/403.","solutions":["Inspect `exc.status` and `exc.headers` from the caught WSServerHandshakeError to see what the server actually returned.","Verify the URL scheme matches the transport (`wss://` for TLS, `ws://` for plain).","Confirm the server actually speaks WebSocket on that path (curl with `--include --http1.1 -H 'Connection: Upgrade' -H 'Upgrade: websocket'`).","Provide required auth/cookies/headers (`headers=`, `cookies=`) or fix the proxy's Upgrade forwarding."],"exampleFix":"// before\nawait session.ws_connect('https://host/api')  # REST endpoint, returns 200\n// after\nawait session.ws_connect('wss://host/ws')   # correct WS endpoint","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    if e.status != 101:\n        log.error('server returned %s, headers=%s', e.status, dict(e.headers))\n        # check scheme/auth/proxy, then retry or fail\n    raise","preventionTips":["Verify the endpoint actually serves WebSocket (correct path + scheme).","Ensure required auth/cookies are attached before ws_connect.","Confirm proxy config forwards the Upgrade headers.","Log `e.status` and `e.headers` to diagnose non-101 responses."],"tags":["client","websocket","handshake","server-misbehavior"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}