{"id":"fce7217dcde46ca0","repo":"aio-libs/aiohttp","slug":"invalid-challenge-response","errorCode":null,"errorMessage":"Invalid challenge response","messagePattern":"Invalid challenge response","errorType":"exception","errorClass":"WSServerHandshakeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":1123,"sourceCode":"                    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                )\n\n            # websocket protocol\n            protocol = None\n            if protocols and hdrs.SEC_WEBSOCKET_PROTOCOL in resp.headers:\n                resp_protocols = [\n                    proto.strip()\n                    for proto in resp.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(\",\")\n                ]\n\n                for proto in resp_protocols:\n                    if proto in protocols:\n                        protocol = proto","sourceCodeStart":1105,"sourceCodeEnd":1141,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L1105-L1141","documentation":"Raised as `WSServerHandshakeError` (client.py:1119-1129) when the server's `Sec-WebSocket-Accept` header doesn't equal `base64(sha1(sec_key + GUID))`. The client generates a random `sec_key`, sends it in `Sec-WebSocket-Key`, and the server must echo back the SHA-1 of that key concatenated with the RFC 6455 GUID (`258EAFA5-E914-47DA-95CA-C5AB0DC85B11`). A mismatch means the server didn't follow the handshake proof — a sign of a broken/non-compliant server or an intermediary rewriting headers.","triggerScenarios":"Server returns 101 with all the right headers but computes the Accept value incorrectly (wrong GUID, wrong hash, or echoes the Key verbatim). Some custom/broken WS servers or test mocks do this.","commonSituations":"Hand-rolled WS server with a buggy Accept computation; mock server that doesn't implement the handshake proof; intermediary that rewrites the Sec-WebSocket-Key and desyncs the proof; server echoing Key instead of hashing.","solutions":["Verify the server implements RFC 6455 §4.2.2 §5 (SHA-1 of `sec_key + \"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"`, base64-encoded).","Compare the client's sent `Sec-WebSocket-Key` (in `exc.request_info.headers`) against what the server received — intermediaries sometimes corrupt it.","Use a known-compliant WS server (autobahn, nginx, a real framework) to isolate the fault.","If testing, ensure your mock computes the Accept correctly rather than returning a placeholder."],"exampleFix":"// before\n# custom server echoes key verbatim in Sec-WebSocket-Accept\n// after (server-side, Python)\nimport hashlib, base64\naccept = base64.b64encode(\n    hashlib.sha1(sec_key.encode() + b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest()\n).decode()","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 'challenge response' in (e.message or '').lower():\n        log.error('Sec-WebSocket-Accept mismatch; server likely non-compliant')\n        # verify server implements RFC 6455 SHA-1+GUID proof\n    raise","preventionTips":["Use an RFC 6455-compliant server (autobahn testsuite to verify).","Inspect whether intermediaries rewrite Sec-WebSocket-Key.","For mocks, compute Accept = base64(sha1(key + GUID))."],"tags":["client","websocket","handshake","protocol","server-misbehavior"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}