{"id":"51d6233dfaa8735b","repo":"aio-libs/aiohttp","slug":"1007-51d623","errorCode":"1007","errorMessage":"Invalid UTF-8 text message","messagePattern":"Invalid UTF-8 text message","errorType":"exception","errorClass":"WebSocketError","httpStatus":null,"severity":"error","filePath":"aiohttp/_websocket/reader_py.py","lineNumber":272,"sourceCode":"                    ),\n                )\n                if self._max_msg_size and len(payload_merged) > self._max_msg_size:\n                    raise WebSocketError(\n                        WSCloseCode.MESSAGE_TOO_BIG,\n                        f\"Decompressed message exceeds size limit {self._max_msg_size}\",\n                    )\n            elif type(assembled_payload) is bytes:\n                payload_merged = assembled_payload\n            else:\n                payload_merged = bytes(assembled_payload)\n\n            size = len(payload_merged)\n            if opcode == OP_CODE_TEXT:\n                if self._decode_text:\n                    try:\n                        text = payload_merged.decode(\"utf-8\")\n                    except UnicodeDecodeError as exc:\n                        raise WebSocketError(\n                            WSCloseCode.INVALID_TEXT, \"Invalid UTF-8 text message\"\n                        ) from exc\n\n                    # XXX: The Text and Binary messages here can be a performance\n                    # bottleneck, so we use tuple.__new__ to improve performance.\n                    # This is not type safe, but many tests should fail in\n                    # test_client_ws_functional.py if this is wrong.\n                    msg = TUPLE_NEW(WSMessageText, (text, size, \"\", WS_MSG_TYPE_TEXT))\n                else:\n                    # Return raw bytes for TEXT messages when decode_text=False\n                    msg = TUPLE_NEW(\n                        WSMessageTextBytes, (payload_merged, size, \"\", WS_MSG_TYPE_TEXT)\n                    )\n            else:\n                msg = TUPLE_NEW(\n                    WSMessageBinary, (payload_merged, size, \"\", WS_MSG_TYPE_BINARY)\n                )\n","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/_websocket/reader_py.py#L254-L290","documentation":"Raised when a final TEXT frame's payload cannot be decoded as UTF-8. RFC 6455 section 8.1 requires TEXT frames to be valid UTF-8; failure is a protocol error closed with code 1007 (INVALID_TEXT). aiohttp decodes eagerly (unless decode_text=False) in _handle_frame at reader_py.py:272.","triggerScenarios":"A peer sends a TEXT (opcode 0x1) frame whose bytes contain invalid UTF-8 sequences (e.g. lone surrogates, truncated multibyte chars), and decode_text is True (the default).","commonSituations":"Peer encodes the message incorrectly (latin-1/cp1252 sent as TEXT), truncation by an intermediary, binary data mislabeled as TEXT, or a fragmented message whose UTF-8 boundary was split across frames and reassembled into invalid bytes.","solutions":["Have the peer send binary data as a BINARY (opcode 0x2) frame instead of TEXT.","Ensure the peer serializes text with UTF-8 specifically.","If you intentionally want raw bytes for TEXT frames, open the WebSocket with decode_text=False and do your own validation."],"exampleFix":"# before\nws = await session.ws_connect(url)  # decodes TEXT as utf-8\n\n# after (opt into raw bytes, validate yourself)\nws = await session.ws_connect(url, decode_text=False)","handlingStrategy":"validation","validationCode":"ws = await session.ws_connect(url, decode_text=False)  # get raw bytes; validate yourself\nraw = msg.data\ntry:\n    text = raw.decode('utf-8')\nexcept UnicodeDecodeError:\n    ...","typeGuard":null,"tryCatchPattern":"msg = await ws.receive()\nif msg.type == aiohttp.WSMsgType.ERROR and ws.exception().code == 1007:\n    await ws.close()","preventionTips":["Send binary payloads as BINARY (opcode 0x2), not TEXT","Ensure peers encode text as UTF-8"],"tags":["websocket","utf-8","text-decoding","rfc6455","server"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}