{"record":{"id":"e206c5fcedb43480","repo":"python/cpython","slug":"can-t-write-str-to-binary-stream","errorCode":null,"errorMessage":"can't write str to binary stream","messagePattern":"can't write str to binary stream","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":957,"sourceCode":"\n        with self._lock:\n            if size < 0:\n                size = len(self._buffer)\n            if len(self._buffer) <= self._pos:\n                return b\"\"\n            newpos = min(len(self._buffer), self._pos + size)\n            b = self._buffer[self._pos : newpos]\n            self._pos = newpos\n            return b.take_bytes()\n\n    def read1(self, size=-1):\n        \"\"\"This is the same as read.\n        \"\"\"\n        return self.read(size)\n\n    def write(self, b):\n        if isinstance(b, str):\n            raise TypeError(\"can't write str to binary stream\")\n        with memoryview(b) as view:\n            if self.closed:\n                raise ValueError(\"write to closed file\")\n\n            n = view.nbytes  # Size of any bytes-like object\n            if n == 0:\n                return 0\n\n            with self._lock:\n                pos = self._pos\n                if pos > len(self._buffer):\n                    # Pad buffer to pos with null bytes.\n                    self._buffer.resize(pos)\n                self._buffer[pos:pos + n] = view\n                self._pos += n\n            return n\n\n    def seek(self, pos, whence=0):","sourceCodeStart":939,"sourceCodeEnd":975,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L939-L975","documentation":"BytesIO.write (Lib/_pyio.py:957) is a binary stream: it wraps its argument in memoryview(b), which requires a bytes-like object. Passing str fails that contract before any buffering, and the method raises TypeError('can't write str to binary stream') to direct you to an encoding step or a text stream.","triggerScenarios":"buf.write('hello') on io.BytesIO; mixing text constants into otherwise-binary writes; passing a value read from a text-mode file into a BytesIO; writing JSON-serialized-as-str (`json.dumps`) instead of bytes.","commonSituations":"Protocols where some fields are text (usernames, URLs) and others binary; json.dumps returning str being written to binary sockets/buffers; refactoring text logs into a BytesIO-backed collector.","solutions":["Encode strings explicitly: `buf.write(s.encode('utf-8'))`.","For JSON payloads use `json.dumps(obj).encode()` or `json.dumps(obj).encode('utf-8')` before writing.","If the stream should hold text, use io.StringIO (or open the target in text mode) instead of BytesIO."],"exampleFix":"# before\nbuf = io.BytesIO()\nbuf.write(json.dumps({'a': 1}))  # str -> TypeError\n\n# after\nbuf = io.BytesIO()\nbuf.write(json.dumps({'a': 1}).encode('utf-8'))","handlingStrategy":"type-guard","validationCode":"if isinstance(data, str):\n    data = data.encode('utf-8')\nbuf.write(data)","typeGuard":"def is_bytes_like(v) -> bool:\n    return not isinstance(v, str) and isinstance(memoryview(v), memoryview)","tryCatchPattern":"try:\n    buf.write(data)\nexcept TypeError as e:\n    if 'str to binary' in str(e):\n        buf.write(data.encode('utf-8'))\n    else:\n        raise","preventionTips":["Encode every str at the boundary: s.encode('utf-8') before binary writes.","For JSON use json.dumps(...).encode() or json.dumps(...).encode('utf-8').","Choose io.StringIO when the payload is genuinely text."],"tags":["io","bytesio","write","typeerror","encoding"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}