{"record":{"id":"8f08de3b1cd08d46","repo":"aio-libs/aiohttp","slug":"wsclosecode-protocol-error","errorCode":"WSCloseCode.PROTOCOL_ERROR","errorMessage":"Continuation frame for non started message","messagePattern":"Continuation frame for non started message","errorType":"exception","errorClass":"WebSocketError","httpStatus":null,"severity":"error","filePath":"aiohttp/_websocket/reader_py.py","lineNumber":205,"sourceCode":"        except Exception as exc:\n            self._exc = exc\n            set_exception(self.queue, exc)\n            return EMPTY_FRAME_ERROR\n\n        return EMPTY_FRAME\n\n    def _handle_frame(\n        self,\n        fin: bool,\n        opcode: int | cython_int,  # Union intended: Cython pxd uses C int\n        payload: bytes | bytearray,\n        compressed: int | cython_int,  # Union intended: Cython pxd uses C int\n    ) -> None:\n        msg: WSMessage\n        if opcode in {OP_CODE_TEXT, OP_CODE_BINARY, OP_CODE_CONTINUATION}:\n            # Validate continuation frames before processing\n            if opcode == OP_CODE_CONTINUATION and self._opcode == OP_CODE_NOT_SET:\n                raise WebSocketError(\n                    WSCloseCode.PROTOCOL_ERROR,\n                    \"Continuation frame for non started message\",\n                )\n\n            # load text/binary\n            if not fin:\n                # got partial frame payload\n                if opcode != OP_CODE_CONTINUATION:\n                    self._opcode = opcode\n                self._partial += payload\n                return\n\n            has_partial = bool(self._partial)\n            if opcode == OP_CODE_CONTINUATION:\n                opcode = self._opcode\n                self._opcode = OP_CODE_NOT_SET\n            # previous frame was non finished\n            # we should get continuation opcode","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d9aaf697c2cd4783ca5749a971965c689f3ec24f/aiohttp/_websocket/reader_py.py#L187-L223","documentation":"Raised as WebSocketError(code=PROTOCOL_ERROR) in WebSocketReader._handle_frame at reader_py.py:205 when a CONTINUATION opcode (0x0) frame arrives but self._opcode is OP_CODE_NOT_SET, i.e. there is no in-progress fragmented text/binary message to continue. Per RFC 6455 a continuation frame must follow a non-final (FIN=0) text/binary frame.","triggerScenarios":"The remote peer sends a frame with opcode 0x0 (continuation) as its very first data frame, or after a previous fragmented message was already completed. Surfaces to the aiohttp user via `await ws.receive()` returning a message with type WSMsgType.ERROR (data is the WebSocketError) and triggers a close with code 1002.","commonSituations":"A buggy or non-conformant client/server implementation; a man-in-the-middle or proxy that reorders/drops frames; a fuzz tester; a peer that restarted its frame state machine mid-stream.","solutions":["Inspect `msg.type == aiohttp.WSMsgType.ERROR` and `msg.data.code` in your receive loop and close the connection cleanly with `await ws.close()`.","If you control the peer, ensure continuation frames are only sent after a FIN=0 text/binary frame.","Reconnect / re-establish the WebSocket session after a PROTOCOL_ERROR, since the stream is no longer trustworthy."],"exampleFix":"// before\nasync for msg in ws:\n    process(msg.data)\n\n# after\nasync for msg in ws:\n    if msg.type == aiohttp.WSMsgType.ERROR:\n        log.warning(\"ws protocol error: %r\", msg.data)\n        await ws.close()\n        break\n    process(msg.data)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"msg = await ws.receive()\nif msg.type == aiohttp.WSMsgType.ERROR:\n    err = msg.data  # WebSocketError with .code == WSCloseCode.PROTOCOL_ERROR\n    await ws.close()\n    return","preventionTips":["Always branch on WSMsgType.ERROR in every receive() / async-for loop; do not assume only data messages arrive.","Treat PROTOCOL_ERROR as fatal: close and reconnect rather than continuing to read.","If you control the peer, only emit continuation frames after a FIN=0 data frame."],"tags":["websocket","protocol","rfc6455","fragmentation","continuation"],"analyzedSha":"d9aaf697c2cd4783ca5749a971965c689f3ec24f","analyzedAt":"2026-08-06T21:30:48.638Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}