{"id":"4e56653e6c232dfa","repo":"aio-libs/aiohttp","slug":"data-argument-must-be-str-r","errorCode":null,"errorMessage":"data argument must be str (%r)","messagePattern":"data argument must be str \\(%r\\)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client_ws.py","lineNumber":287,"sourceCode":"\n    def exception(self) -> BaseException | None:\n        return self._exception\n\n    async def ping(self, message: bytes = b\"\") -> None:\n        await self._writer.send_frame(message, WSMsgType.PING)\n\n    async def pong(self, message: bytes = b\"\") -> None:\n        await self._writer.send_frame(message, WSMsgType.PONG)\n\n    async def send_frame(\n        self, message: bytes, opcode: WSMsgType, compress: int | None = None\n    ) -> None:\n        \"\"\"Send a frame over the websocket.\"\"\"\n        await self._writer.send_frame(message, opcode, compress)\n\n    async def send_str(self, data: str, compress: int | None = None) -> None:\n        if not isinstance(data, str):\n            raise TypeError(\"data argument must be str (%r)\" % type(data))\n        await self._writer.send_frame(\n            data.encode(\"utf-8\"), WSMsgType.TEXT, compress=compress\n        )\n\n    async def send_bytes(self, data: bytes, compress: int | None = None) -> None:\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(\"data argument must be byte-ish (%r)\" % type(data))\n        await self._writer.send_frame(data, WSMsgType.BINARY, compress=compress)\n\n    async def send_json(\n        self,\n        data: Any,\n        compress: int | None = None,\n        *,\n        dumps: JSONEncoder = DEFAULT_JSON_ENCODER,\n    ) -> None:\n        await self.send_str(dumps(data), compress=compress)\n","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client_ws.py#L269-L305","documentation":"Raised as TypeError in ClientWebSocketResponse.send_str() when the data argument is not a str. WebSocket text frames must carry text; sending bytes via send_str would silently mis-encode the frame, so the type is enforced strictly.","triggerScenarios":"Fires at line 286-287 when isinstance(data, str) is False. Triggered by passing bytes (b'hello'), a dict (use send_json), an int, or None to send_str.","commonSituations":"Passing already-encoded UTF-8 bytes to send_str instead of send_bytes; passing JSON-serialized bytes; passing a non-string from dynamic code.","solutions":["Pass a str to send_str: await ws.send_str('hello').","For bytes use send_bytes: await ws.send_bytes(b'hello').","For JSON use send_json: await ws.send_json({'k': 1}).","Decode bytes to str first: data.decode('utf-8') if you have UTF-8 text bytes."],"exampleFix":"# before\nawait ws.send_str(b'hello')      # bytes\nawait ws.send_str({'k': 1})     # dict\n# after\nawait ws.send_str('hello')\nawait ws.send_bytes(b'hello')\nawait ws.send_json({'k': 1})","handlingStrategy":"type-guard","validationCode":"if not isinstance(data, str):\n    raise TypeError(f'send_str requires str, got {type(data).__name__}')\nawait ws.send_str(data)","typeGuard":"def is_ws_text(data) -> bool:\n    return isinstance(data, str)","tryCatchPattern":null,"preventionTips":["Use send_str for str, send_bytes for bytes, send_json for objects.","Encode cross-type payloads explicitly before sending.","Add type annotations on WS send helpers to catch mistakes statically."],"tags":["websocket","type-error","validation","client-ws"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}