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 character

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Encode the input to bytes first: load(data.encode('utf-8')) only if it was wrongly decoded, otherwise pass the raw bytes
  2. Read sockets/files in binary mode so you receive bytes
  3. If you have a bytearray/memoryview, wrap with bytes() before calling load
  4. 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

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


AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27). Data as JSON: /api/errors/6443f8b04c0133c8. Report an issue: GitHub.