{"id":"77659189f302f82e","repo":"aio-libs/aiohttp","slug":"1002-776591","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_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/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/_websocket/reader_py.py#L187-L223","documentation":"Identical semantics to error [4]: WebSocketError (1002 PROTOCOL_ERROR) for a CONTINUATION frame with no preceding non-final TEXT/BINARY frame. The difference is purely the implementation: this one is raised by the PURE-PYTHON reader (reader_py.py) used when Cython extensions are disabled (AIOHTTP_NO_EXTENSIONS=1) or not compiled. Behavior, close code, and surfacing (msg.type == WSMsgType.ERROR) are the same as the Cython variant.","triggerScenarios":"Same as [4]: a CONTINUATION (0x0) frame arrives while self._opcode == OP_CODE_NOT_SET. You only see reader_py.py in the traceback when extensions are off (AIOHTTP_NO_EXTENSIONS=1) or the C extension import failed.","commonSituations":"Running with AIOHTTP_NO_EXTENSIONS=1 for debugging; a broken/missing Cython build (pip install without compiling extensions); CI environments that force pure-Python mode. The underlying peer bug is the same as [4].","solutions":["Handle msg.type == WSMsgType.ERROR / code 1002 in the receive loop and close.","Ensure the peer starts each fragmented message with a TEXT/BINARY frame before CONTINUATION.","If you did not intend pure-Python mode, build the extensions ('pip install -e .' / make cythonize) to move to the Cython reader; the bug itself is on the peer.","Rule out a frame-corrupting intermediary."],"exampleFix":"# before\nPYTHONPATH=. AIOHTTP_NO_EXTENSIONS=1 python app.py  # reader_py.py path\nmsg = await ws.receive()\n\n# after\nmsg = await ws.receive()\nif msg.type is aiohttp.WSMsgType.ERROR:\n    log.warning('protocol error (pure-py reader): %s', msg.data)\n    await ws.close()","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"from aiohttp import WSMsgType\n\ndef is_ws_error(msg) -> bool:\n    return msg.type is WSMsgType.ERROR","tryCatchPattern":"msg = await ws.receive()\nif msg.type is aiohttp.WSMsgType.ERROR:\n    exc = msg.data  # WebSocketError with .code == 1002\n    log.warning('continuation-without-start (pure-py reader): %s', exc)\n    await ws.close()","preventionTips":["Same protocol guard as the Cython reader: handle WSMsgType.ERROR and inspect msg.data.code.","If you did not intend pure-Python mode, build the C extensions so the Cython reader is used.","Ensure the peer starts each fragmented message with TEXT/BINARY before CONTINUATION."],"tags":["websocket","protocol","fragmentation","pure-python","close-1002"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}