python/cpython · error · TypeError
can't write str to binary stream
Error message
can't write str to binary stream
What it means
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.
Source
Thrown at Lib/_pyio.py:957
with self._lock:
if size < 0:
size = len(self._buffer)
if len(self._buffer) <= self._pos:
return b""
newpos = min(len(self._buffer), self._pos + size)
b = self._buffer[self._pos : newpos]
self._pos = newpos
return b.take_bytes()
def read1(self, size=-1):
"""This is the same as read.
"""
return self.read(size)
def write(self, b):
if isinstance(b, str):
raise TypeError("can't write str to binary stream")
with memoryview(b) as view:
if self.closed:
raise ValueError("write to closed file")
n = view.nbytes # Size of any bytes-like object
if n == 0:
return 0
with self._lock:
pos = self._pos
if pos > len(self._buffer):
# Pad buffer to pos with null bytes.
self._buffer.resize(pos)
self._buffer[pos:pos + n] = view
self._pos += n
return n
def seek(self, pos, whence=0):View on GitHub (pinned to bc6749cc3b)
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.
Example fix
# before
buf = io.BytesIO()
buf.write(json.dumps({'a': 1})) # str -> TypeError
# after
buf = io.BytesIO()
buf.write(json.dumps({'a': 1}).encode('utf-8')) Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(data, str):
data = data.encode('utf-8')
buf.write(data) Type guard
def is_bytes_like(v) -> bool:
return not isinstance(v, str) and isinstance(memoryview(v), memoryview) Try / catch
try:
buf.write(data)
except TypeError as e:
if 'str to binary' in str(e):
buf.write(data.encode('utf-8'))
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/e206c5fcedb43480.
Report an issue: GitHub.