Textualize/textual · error · TypeError
must be bytes
Error message
must be bytes
What it means
load() in textual._binary_encode expects the wire format to be bytes and rejects anything else with TypeError('must be bytes') before decoding starts. This is a strict input-type contract for the internal binary protocol.
Source
Thrown at src/textual/_binary_encode.py:182
return decoder(datum)
return encode(data)
def load(encoded: bytes) -> object:
"""Load an encoded data structure from bytes.
Args:
encoded: Encoded data in bytes.
Raises:
DecodeError: If an error was encountered decoding the string.
Returns:
Decoded data.
"""
if not isinstance(encoded, bytes):
raise TypeError("must be bytes")
max_position = len(encoded)
position = 0
def get_byte() -> bytes:
"""Get an encoded byte and advance position.
Raises:
DecodeError: If the end of the data was reached
Returns:
A bytes object with a single byte.
"""
nonlocal position
if position >= max_position:
raise DecodeError("More data expected")
character = encoded[position : position + 1]
position += 1
return characterView on GitHub (pinned to 06dbeef4bb)
Solutions
- Encode the input to bytes first: load(data.encode('utf-8')) only if it was wrongly decoded, otherwise pass the raw bytes
- Read sockets/files in binary mode so you receive bytes
- If you have a bytearray/memoryview, wrap with bytes() before calling load
- Verify you are not passing an already-decoded Python object
Example fix
# before
load('{"a": 1}') # TypeError: must be bytes
# after
load(b'\x00\x01...') # raw encoded bytes Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(payload, (bytes, bytearray)):
payload = bytes(payload, 'utf-8') # or raise early with context
load(payload) Type guard
def is_encoded_bytes(data: object) -> bool:
return isinstance(data, (bytes, bytearray)) and not isinstance(data, str) Try / catch
try:
load(payload)
except TypeError as e:
if 'must be bytes' in str(e):
load(payload.encode('utf-8'))
raise Prevention
- Open files/sockets in binary mode
- Convert bytearray/memoryview with bytes() before load
- Never pass str from text-mode transports directly
When it happens
Trigger: Calling load() with a str (e.g. a decoded string from a socket), a bytearray, memoryview, or None instead of bytes.
Common situations: Reading data from a transport that yields str (text-mode files, WebSocket text frames) and passing it directly; test code passing string literals; accidentally double-decoding an already-decoded payload.
Related errors
- Can't encode {datum!r}
- Don't know how to animate {value!r}; Can only animate <int>,
- More data expected
- Missing bytes in {bytes_data!r}
- No handler for {event_name!r}
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/6443f8b04c0133c8.
Report an issue: GitHub.