Textualize/textual · error · TypeError

Can't encode {datum!r}

Error message

Can't encode {datum!r}

What it means

Textual's internal binary encoder (used for the devtools/serving protocol) only supports a fixed set of types (int, float, str, bytes, bool, None, list, tuple, dict). encode() looks up the type in the ENCODERS registry and raises TypeError when the datum's type is not registered. Note: the message string lacks an f-prefix in this version, so it prints literally '{datum!r}'.

Source

Thrown at src/textual/_binary_encode.py:163

        dict: encode_dict,
    }

    def encode(datum: object) -> bytes:
        """Recursively encode data.

        Args:
            datum: Data suitable for encoding.

        Raises:
            TypeError: If `datum` is not one of the supported types.

        Returns:
            Encoded data bytes.
        """
        try:
            decoder = ENCODERS[type(datum)]
        except KeyError:
            raise TypeError("Can't encode {datum!r}") from None
        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):

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Convert unsupported values to supported primitives before encoding (str(), list(), dict(...))
  2. Replace sets with lists or tuples, datetimes with ISO strings, dataclasses with dicts
  3. Restrict payloads to JSON-like types (int, float, str, bytes, bool, None, list, tuple, dict)
  4. Avoid the private _binary_encode module in user code; use JSON or pickle explicitly

Example fix

# before
encode({"tags": {"a", "b"}})  # TypeError: Can't encode

# after
encode({"tags": ["a", "b"]})
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = (int, float, str, bytes, bool, type(None), list, tuple, dict)
def sanitize(data):
    if isinstance(data, dict):
        return {k: sanitize(v) for k, v in data.items()}
    if isinstance(data, (list, tuple)):
        return [sanitize(v) for v in data]
    if isinstance(data, ALLOWED):
        return data
    return str(data)

Type guard

def is_encodable(datum: object) -> bool:
    return isinstance(datum, (int, float, str, bytes, bool, type(None), list, tuple, dict))

Try / catch

try:
    encode(data)
except TypeError:
    encode(sanitize(data))

Prevention

When it happens

Trigger: Calling textual._binary_encode.dump/encode with an unsupported value such as a set, datetime, custom class, complex, or numpy scalar nested inside the payload.

Common situations: Serializing app state or snapshot payloads for the devtools connection that contain enums, sets, datetimes, or dataclasses; private-API users dumping arbitrary Python objects.

Related errors


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