python/cpython · warning · TypeError

write() argument must be bytes-like, not {type(b).__name__}

Error message

write() argument must be bytes-like, not {type(b).__name__}

What it means

Debug-mode guard in BaseSelectorEventLoop.sock_sendall(): the loop verifies the socket is non-blocking before driving a full send, since a blocking socket could stall the loop inside send() indefinitely. With self._debug on and sock.gettimeout() != 0 the call fails immediately with ValueError.

Source

Thrown at Lib/_apple_support.py:55


class LogStream(io.RawIOBase):
    def __init__(self, log_write, level):
        self.log_write = log_write
        self.level = level

    def __repr__(self):
        return f"<LogStream (level {self.level!r})>"

    def writable(self):
        return True

    def write(self, b):
        if type(b) is not bytes:
            try:
                b = bytes(memoryview(b))
            except TypeError:
                raise TypeError(
                    f"write() argument must be bytes-like, not {type(b).__name__}"
                ) from None

        # Writing an empty string to the stream should have no effect.
        if b:
            # Encode null bytes using "modified UTF-8" to avoid truncating the
            # message. This should not affect the return value, as the caller
            # may be expecting it to match the length of the input.
            self.log_write(self.level, b.replace(b"\x00", b"\xc0\x80"))

        return len(b)

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. sock.setblocking(False) before using sock_sendall
  2. Create and connect sockets via loop.sock_connect on a non-blocking socket end to end
  3. Guard shared sockets with an assertion in tests: assert sock.gettimeout() == 0

Example fix

# before
sock = socket.create_connection(addr)  # blocking
await loop.sock_sendall(sock, payload)  # debug: ValueError
# after
sock = socket.socket(); sock.setblocking(False)
await loop.sock_connect(sock, addr)
await loop.sock_sendall(sock, payload)
Defensive patterns

Strategy: validation

Validate before calling

sock = socket.socket()
sock.setblocking(False)
await loop.sock_connect(sock, addr)      # non-blocking end to end
await loop.sock_sendall(sock, payload)

Try / catch

try:
    await loop.sock_sendall(sock, data)
except ValueError as e:
    if 'non-blocking' in str(e):
        sock.setblocking(False)
        return await loop.sock_sendall(sock, data)
    raise

Prevention

When it happens

Trigger: await loop.sock_sendall(sock, data) with asyncio debug enabled and a blocking/timeout-configured socket — including sockets obtained from getaddrinfo-plus-connect sync flows, or inherited from libraries that set timeouts for their own retry logic.

Common situations: Debugging a stalled sender by enabling debug mode and hitting this earlier, clearer error; mixing a sync client library's socket into loop-based sending; porting threaded senders to coroutines without flipping blocking mode.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/7296bee69f2193cb. Report an issue: GitHub.