{"record":{"id":"c0094f0d3d238708","repo":"aio-libs/aiohttp","slug":"unsupported-version-version","errorCode":null,"errorMessage":"Unsupported version: {version}","messagePattern":"Unsupported version: (.+?)","errorType":"http","errorClass":"HTTPBadRequest","httpStatus":400,"severity":"error","filePath":"aiohttp/web_ws.py","lineNumber":311,"sourceCode":"            ]\n\n            for proto in req_protocols:\n                if proto in self._protocols:\n                    protocol = proto\n                    break\n            else:\n                # No overlap found: Return no protocol as per spec\n                ws_logger.warning(\n                    \"%s: Client protocols %r don’t overlap server-known ones %r\",\n                    request.remote,\n                    req_protocols,\n                    self._protocols,\n                )\n\n        # check supported version\n        version = headers.get(hdrs.SEC_WEBSOCKET_VERSION, \"\")\n        if version not in (\"13\", \"8\", \"7\"):\n            raise HTTPBadRequest(text=f\"Unsupported version: {version}\")\n\n        # check client handshake for validity\n        key = headers.get(hdrs.SEC_WEBSOCKET_KEY)\n        try:\n            if not key or len(base64.b64decode(key)) != 16:\n                raise HTTPBadRequest(text=f\"Handshake error: {key!r}\")\n        except binascii.Error:\n            raise HTTPBadRequest(text=f\"Handshake error: {key!r}\") from None\n\n        accept_val = base64.b64encode(\n            hashlib.sha1(key.encode() + WS_KEY).digest()\n        ).decode()\n        response_headers = CIMultiDict(\n            {\n                hdrs.UPGRADE: \"websocket\",\n                hdrs.CONNECTION: \"upgrade\",\n                hdrs.SEC_WEBSOCKET_ACCEPT: accept_val,\n            }","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_ws.py#L293-L329","documentation":"_handshake() checks the Sec-WebSocket-Version header against the supported set {13, 8, 7} (RFC 6455 and its two drafts). Any other value (missing, empty, '12', etc.) returns HTTP 400. Version 13 is the standard (RFC 6455); 8 and 7 are legacy drafts kept for backward compatibility.","triggerScenarios":"A client sends an outdated draft version (e.g. '6' or 'hixie-76'); the header is missing entirely (defaults to ''); a malformed/forged request with a non-numeric value; an extremely old browser library.","commonSituations":"Legacy client libraries from the draft era; misbehaving bots/scanners sending probe requests; intermediaries that strip the version header; tests with hand-built handshake requests that forget the version.","solutions":["Ensure the client sends 'Sec-WebSocket-Version: 13' (all modern browsers and the aiohttp client do this by default).","Upgrade client libraries to one supporting RFC 6455.","If supporting legacy drafts is unnecessary, treat this 400 as expected behaviour for malformed clients."],"exampleFix":"// before — hand-built request missing version\n// headers: {Upgrade: websocket, Connection: Upgrade, ...}\n// after\n// headers: {Upgrade: websocket, Connection: Upgrade, 'Sec-WebSocket-Version': '13', 'Sec-WebSocket-Key': '<base64 16 bytes>'}","handlingStrategy":"validation","validationCode":"SUPPORTED_WS_VERSIONS = {'13', '8', '7'}\n\ndef is_supported_ws_version(request) -> bool:\n    return request.headers.get('Sec-WebSocket-Version', '') in SUPPORTED_WS_VERSIONS\n\nif not is_supported_ws_version(request):\n    return web.Response(status=400, text='unsupported WS version')","typeGuard":"def has_valid_ws_version(request) -> bool:\n    return request.headers.get('Sec-WebSocket-Version', '') == '13'","tryCatchPattern":"ws = web.WebSocketResponse()\ntry:\n    await ws.prepare(request)\nexcept web.HTTPBadRequest as e:\n    if 'Unsupported version' in (e.text or ''):\n        log.info('client sent unsupported WS version, rejecting')\n    return","preventionTips":["Use modern clients that send Sec-WebSocket-Version: 13 (RFC 6455).","Don't try to support pre-RFC draft versions unless you have a known legacy client.","Log rejected handshakes at info level — most are probes/scanners."],"tags":["websocket","handshake","protocol-version","rfc6455"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}