pypa/pip · error · TypeError

Cannot serialize {obj!r}

Error message

Cannot serialize {obj!r}

What it means

Raised by msgpack's pure-Python Packer._pack as the final fallthrough when the object does not match any serializable type (None, bool, int, float, bytes, bytearray, str, memoryview, ExtType, Timestamp, list, tuple, dict, or timezone-aware datetime) AND either no default callback was provided or the default callback was already invoked once and still returned an unserializable value. This is a TypeError, meaning the input type is fundamentally unsupported.

Source

Thrown at src/pip/_vendor/msgpack/fallback.py:804

                    self._pack(obj[i], nest_limit - 1)
                return
            if check(obj, dict):
                return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1)

            if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None:
                obj = Timestamp.from_datetime(obj)
                default_used = 1
                continue

            if not default_used and self._default is not None:
                obj = self._default(obj)
                default_used = 1
                continue

            if self._datetime and check(obj, _DateTime):
                raise ValueError(f"Cannot serialize {obj!r} where tzinfo=None")

            raise TypeError(f"Cannot serialize {obj!r}")

    def pack(self, obj):
        try:
            self._pack(obj)
        except:
            self._buffer = BytesIO()  # force reset
            raise
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = BytesIO()
            return ret

    def pack_map_pairs(self, pairs):
        self._pack_map_pairs(len(pairs), pairs)
        if self._autoreset:
            ret = self._buffer.getvalue()
            self._buffer = BytesIO()
            return ret

View on GitHub (pinned to f399c37189)

Solutions

  1. Provide a default callback to Packer(default=my_func) or packb(obj, default=my_func) that converts unsupported types to dict/list/primitives.
  2. Convert sets to lists and custom objects to dicts before packing.
  3. Use recursion-safe default handlers that handle each custom type, since default is only called once per object.
  4. For dataclasses, use dataclasses.asdict() before packing.

Example fix

# before
packer = msgpack.Packer()
packer.pack({1, 2, 3})  # set — raises TypeError

# after — provide a default handler
def default(obj):
    if isinstance(obj, set):
        return list(obj)
    raise TypeError(f'Cannot serialize {obj!r}')
packer = msgpack.Packer(default=default)
packer.pack({1, 2, 3})
Defensive patterns

Strategy: try-catch

Validate before calling

import msgpack
from datetime import datetime, timezone

def default_serializer(obj):
    if isinstance(obj, set):
        return list(obj)
    if hasattr(obj, '__dict__'):
        return obj.__dict__
    raise TypeError(f'Cannot serialize {type(obj).__name__}')

packer = msgpack.Packer(default=default_serializer)

Type guard

MSGPACK_TYPES = (type(None), bool, int, float, bytes, bytearray, str, memoryview, list, tuple, dict)

def is_msgpack_native(obj) -> bool:
    return isinstance(obj, MSGPACK_TYPES)

Try / catch

try:
    packed = packer.pack(obj)
except TypeError as e:
    if 'Cannot serialize' in str(e):
        packed = packer.pack(str(obj))  # or convert to dict
    else:
        raise

Prevention

When it happens

Trigger: Packing a custom class instance, set, frozenset, complex, range, or any other object not in msgpack's native type table without providing a default serializer. Also raised when the default callback returns a value that is itself unserializable.

Common situations: Serializing ORM model instances, dataclasses, or custom objects without a default function; packing a set instead of a list; nested custom objects where default only handles the top level.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/8d3fde0275d14e82. Report an issue: GitHub.