{"record":{"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":"exception","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/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/client_ws.py#L269-L305","documentation":"Raised by ClientWebSocketResponse.send_str() when the 'data' argument is not a str. send_str encodes the string to UTF-8 and sends a TEXT frame; passing bytes, int, dict, or None is a type error caught by an isinstance check before any frame is written. Use send_bytes() for binary data or send_json() for JSON-serializable objects.","triggerScenarios":"Calling await ws.send_str(b'hello') (bytes), ws.send_str(42), ws.send_str({'k':'v'}), or any non-str value. The isinstance(data, str) check fails and TypeError is raised immediately, before the frame is sent.","commonSituations":"Passing bytes that should be str (or vice versa); JSON-encoding with a bytes-returning encoder (e.g. orjson.dumps) into send_str instead of send_str via send_json_bytes; reading a value from a source typed as Any and not converting; confusing send_str with send_bytes.","solutions":["Ensure the argument is a str: await ws.send_str(value.decode() if isinstance(value, bytes) else value).","For binary data use await ws.send_bytes(data).","For JSON use await ws.send_json(obj) — and if your encoder returns bytes, use send_json_bytes().","Add a type check or cast at the call site when data comes from an untyped source."],"exampleFix":"# before\nawait ws.send_str(b'hello')        # bytes -> TypeError\nawait ws.send_str(orjson.dumps(x))  # bytes -> TypeError\n\n# after\nawait ws.send_str('hello')                 # str\nawait ws.send_bytes(b'hello')              # bytes via send_bytes\nawait ws.send_json_bytes(x, dumps=orjson.dumps)  # bytes encoder -> binary frame","handlingStrategy":"type-guard","validationCode":"async def safe_send_str(ws, data):\n    if isinstance(data, str):\n        await ws.send_str(data)\n    elif isinstance(data, (bytes, bytearray, memoryview)):\n        await ws.send_bytes(bytes(data))\n    else:\n        await ws.send_json(data)  # or raise","typeGuard":"def is_ws_text(data) -> bool:\n    return isinstance(data, str)","tryCatchPattern":"try:\n    await ws.send_str(value)\nexcept TypeError as e:\n    if 'must be str' in str(e):\n        if isinstance(value, (bytes, bytearray)):\n            await ws.send_bytes(value)\n        else:\n            await ws.send_json(value)\n    else:\n        raise","preventionTips":["Match the API to the data type: send_str for str, send_bytes for binary, send_json for objects.","For bytes-returning JSON encoders (orjson), use send_json_bytes.","Add isinstance checks at boundaries when data arrives untyped."],"tags":["websocket","client","type-error","websocket-message","usage"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}