{"record":{"id":"58af288ca5cb1a36","repo":"aio-libs/aiohttp","slug":"1002","errorCode":"1002","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_c.py","lineNumber":208,"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":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/_websocket/reader_c.py#L190-L226","documentation":"A WebSocket CONTINUATION frame (opcode 0x00) arrived but the reader has no outstanding fragmented message (`_opcode == OP_CODE_NOT_SET`). RFC 6455 §5.4 requires a continuation frame to follow a non-final (fin=0) text/binary frame. The parser treats this as a protocol error and closes the connection with code 1002. It is delivered to user code as a `WSMessageError` in the `receive()` loop, not as a thrown exception.","triggerScenarios":"The remote peer sends opcode 0x00 as the very first frame of a message, or immediately after a completed message — i.e. a continuation with no preceding non-fin data frame. Fires in `_handle_frame` at `reader_c.py:208`.","commonSituations":"Buggy peer fragmentation logic; a proxy/MitM reorders frames; a fuzzer/attacker sending raw frames; a peer library bug that opens a fragmented message with the continuation opcode.","solutions":["Fix the peer so a fragmented message starts with TEXT/BINARY (fin=0) and continues with CONTINUATION frames.","Handle `WSMsgType.ERROR` in your receive loop and reconnect — the malformed peer cannot be recovered mid-stream.","If you control the peer, validate its frame sequence with a WS conformance suite."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_error(msg) -> bool:\n    return msg.type == aiohttp.WSMsgType.ERROR","tryCatchPattern":"msg = await ws.receive()\nif msg.type == aiohttp.WSMsgType.ERROR:\n    exc = msg.data            # a WebSocketError\n    close_code = exc.code     # 1002/1007/1009/...\n    log.warning(\"ws protocol error %s: %s\", close_code, exc)","preventionTips":["Always check `msg.type == WSMsgType.ERROR` in receive loops; `msg.data` is the `WebSocketError` with `.code`.","On a 1002 protocol error, close and reconnect rather than continuing."],"tags":["websocket","protocol","fragmentation","rfc6455","close-code-1002"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}