python/cpython · error · TypeError
data argument must be a bytes, bytearray, or memoryview obje
Error message
data argument must be a bytes, bytearray, or memoryview object, not {type(data).__name__!r} What it means
Raised by _SelectorSocketTransport.write() as TypeError when the data argument is not an instance of bytes, bytearray, or memoryview. Transports move raw bytes only; unlike sockets or some third-party APIs they do not accept str. Note that even a 'wrong' object with a buffer protocol that is not one of these three exact types is rejected.
Source
Thrown at Lib/asyncio/selector_events.py:1063
keep_open = self._protocol.eof_received()
except (SystemExit, KeyboardInterrupt):
raise
except BaseException as exc:
self._fatal_error(
exc, 'Fatal error: protocol.eof_received() call failed.')
return
if keep_open:
# We're keeping the connection open so the
# protocol can write more, but we still can't
# receive more, so remove the reader callback.
self._loop._remove_reader(self._sock_fd)
else:
self.close()
def write(self, data):
if not isinstance(data, (bytes, bytearray, memoryview)):
raise TypeError(f'data argument must be a bytes, bytearray, or memoryview '
f'object, not {type(data).__name__!r}')
if self._eof:
raise RuntimeError('Cannot call write() after write_eof()')
if self._empty_waiter is not None:
raise RuntimeError('unable to write; sendfile is in progress')
if not data:
return
if self._conn_lost:
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
logger.warning('socket.send() raised exception.')
self._conn_lost += 1
return
if not self._buffer:
# Optimization: try to send now.
try:
n = self._sock.send(data)View on GitHub (pinned to bc6749cc3b)
Solutions
- Encode strings before writing: transport.write(text.encode('utf-8')).
- Convert arbitrary objects to bytes explicitly (bytes(obj), obj.tobytes(), json.dumps(...).encode()).
- Add a small wrapper or type guard in your protocol layer that asserts isinstance(data, (bytes, bytearray, memoryview)) before delegating to the transport.
Example fix
// before
writer.write(f"ping\n") # str -> TypeError
// after
writer.write(f"ping\n".encode("utf-8"))
await writer.drain() Defensive patterns
Strategy: type-guard
Validate before calling
from typing import Any
def to_bytes(data: Any) -> bytes:
if isinstance(data, str):
return data.encode('utf-8')
if isinstance(data, (bytes, bytearray, memoryview)):
return bytes(data)
raise TypeError(f'cannot serialize {type(data).__name__} for transport') Type guard
BytesLike = (bytes, bytearray, memoryview)
def is_writable_data(data) -> bool:
return isinstance(data, BytesLike) Try / catch
try:
transport.write(data)
except TypeError as e:
if 'data argument' in str(e):
transport.write(str(data).encode('utf-8'))
else:
raise Prevention
- Encode at the edge: convert str to bytes at the API boundary, never inside transport code.
- Use type annotations (bytes) plus mypy to catch str/bytes confusion statically.
- Write a send() wrapper in your protocol class that type-checks payloads once.
When it happens
Trigger: Calling transport.write('hello') (str), transport.write(123), transport.write(['a','b']), or an arbitrary object, on a transport returned by loop.create_connection()/create_server() (typically wrapped by StreamWriter.write which forwards to the transport).
Common situations: Forgetting .encode() on a string when migrating from a library whose send() accepted str (e.g. websocket or zeromq wrappers); passing serialized-but-not-yet-encoded objects; passing a numpy array or other buffer type instead of its bytes() representation.
Related errors
- Cannot call write() after write_eof()
- unable to write; sendfile is in progress
- Cannot call writelines() after write_eof()
- data argument must be a bytes-like object, not {type(data)._
- data: expecting a bytes-like instance, got {type(data).__nam
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/2e3b10e350eadbe3.
Report an issue: GitHub.