python/cpython · warning · TypeError
write() argument must be str, not {type(s).__name__}
Error message
write() argument must be str, not {type(s).__name__} What it means
Debug-mode guard in BaseSelectorEventLoop.sock_recv_into(): before scheduling an asynchronous read into a caller-provided buffer, the loop asserts the socket is non-blocking. A blocking socket would make the eventual recv_into call stall the entire event loop, so debug mode converts the latent hang into an immediate ValueError.
Source
Thrown at Lib/_android_support.py:61
fileno = None
# The default is surrogateescape for stdout and backslashreplace for
# stderr, but in the context of an Android log, readability is more
# important than reversibility.
kwargs.setdefault("encoding", "UTF-8")
kwargs.setdefault("errors", "backslashreplace")
super().__init__(BinaryLogStream(prio, tag, fileno), **kwargs)
self._lock = RLock()
self._pending_bytes = []
self._pending_bytes_count = 0
def __repr__(self):
return f"<TextLogStream {self.buffer.tag!r}>"
def write(self, s):
if not isinstance(s, str):
raise TypeError(
f"write() argument must be str, not {type(s).__name__}")
# In case `s` is a str subclass that writes itself to stdout or stderr
# when we call its methods, convert it to an actual str.
s = str.__str__(s)
# We want to emit one log message per line wherever possible, so split
# the string into lines first. Note that "".splitlines() == [], so
# nothing will be logged for an empty string.
with self._lock:
for line in s.splitlines(keepends=True):
while line:
chunk = line[:MAX_CHARS_PER_WRITE]
line = line[MAX_CHARS_PER_WRITE:]
self._write_chunk(chunk)
return len(s)
View on GitHub (pinned to bc6749cc3b)
Solutions
- Call sock.setblocking(False) on every socket handed to sock_recv_into
- Create sockets inside async code with blocking off from the start
- Audit shared connection pools so all consumers agree on blocking mode; add an assertion sock.gettimeout() == 0 in test doubles
Example fix
# before sock.settimeout(5) await loop.sock_recv_into(sock, buf) # debug: ValueError # after sock.setblocking(False) await loop.sock_recv_into(sock, buf)
Defensive patterns
Strategy: validation
Validate before calling
def nb(sock):
if sock.gettimeout() != 0:
sock.setblocking(False)
return sock
n = await loop.sock_recv_into(nb(sock), buf) Try / catch
try:
await loop.sock_recv_into(sock, buf)
except ValueError as e:
if 'non-blocking' in str(e):
sock.setblocking(False)
return await loop.sock_recv_into(sock, buf)
raise Prevention
- Flip blocking off before the first await on a socket
- Audit migrated recv_into code paths for leftover timeouts
- Use wait_for() to bound receive durations
- Keep a single factory for loop-ready sockets
When it happens
Trigger: await loop.sock_recv_into(sock, buf) with loop debug enabled and sock.gettimeout() != 0 — i.e. blocking default sockets or those configured with settimeout(n). Common when reusing sockets established by synchronous helper APIs.
Common situations: High-throughput readers migrated from blocking recv_into code that never set non-blocking mode; benchmarking under debug builds; socket pools created by sync connection factories feeding into async consumers.
Related errors
- Must run this script from the repo root
- AIX_BUILDDATE is not defined or invalid: {build_date!r}
- write() argument must be str, not {type(s).__name__}
- write() argument must be bytes-like, not {type(b).__name__}
- write() argument must be bytes-like, not {type(b).__name__}
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/6d87c31a67ab1ed2.
Report an issue: GitHub.