cocoindex-io/cocoindex · error · NotImplementedError
Cannot serialize {type(obj).__name__}
Error message
Cannot serialize {type(obj).__name__} What it means
serde.py's msgspec encoder uses an enc_hook to serialize types msgspec does not natively handle. It supports registered safe-picklable globals and Pydantic models; anything else raises NotImplementedError('Cannot serialize <TypeName>'). The error means the object's type is not on the encoder's allowlist.
Source
Thrown at python/cocoindex/_internal/serde.py:281
# ---------------------------------------------------------------------------
# Serialization hooks (cross-pollination bridge)
# ---------------------------------------------------------------------------
def _enc_hook(obj: Any) -> Any:
"""Msgspec enc_hook: handles types msgspec can't encode natively."""
# C: Quarantine pickle types (check first — explicit opt-in wins)
if type(obj) in _SERIALIZE_BY_PICKLE_TYPES:
return msgspec.msgpack.Ext(100, _strict_pickle_dumps(obj))
key = (type(obj).__module__, type(obj).__qualname__)
if key in _UNPICKLE_SAFE_GLOBALS:
return msgspec.msgpack.Ext(100, _strict_pickle_dumps(obj))
# B: Bridge Pydantic into msgspec
if _is_pydantic_instance(obj):
return obj.model_dump(mode="json")
raise NotImplementedError(f"Cannot serialize {type(obj).__name__}")
_msgspec_encoder = msgspec.msgpack.Encoder(enc_hook=_enc_hook)
# ---------------------------------------------------------------------------
# Deserialization hooks
# ---------------------------------------------------------------------------
def _ext_hook(code: int, data: memoryview) -> Any: # type: ignore[type-arg]
"""Un-quarantine pickle inside msgspec payloads."""
if code == 100:
return _RestrictedUnpickler(io.BytesIO(bytes(data))).load()
raise ValueError(f"Unknown extension code: {code}")
def _dec_hook(type_hint: Any, obj: Any) -> Any:View on GitHub (pinned to e84aa99b32)
Solutions
- Register the type in _UNPICKLE_SAFE_GLOBALS (or the corresponding registration API) so it is pickled via the strict pickle path.
- Convert the object to a supported type (Pydantic model, dict of primitives, bytes) before serialization.
- Implement serialization support by making the value a Pydantic model, which the encoder bridges via model_dump(mode='json').
- Catch NotImplementedError at the boundary and store a fallback plain-data representation.
Example fix
// before
return MyCustomClass(x=1) # NotImplementedError from _enc_hook
// after
from pydantic import BaseModel
class Result(BaseModel):
x: int
return Result(x=1) # serialized via model_dump Defensive patterns
Strategy: try-catch
Validate before calling
def is_serializable(obj: object) -> bool:
from cocoindex._internal import serde
key = (type(obj).__module__, type(obj).__qualname__)
return key in serde._UNPICKLE_SAFE_GLOBALS or serde._is_pydantic_instance(obj) Type guard
def is_encodable(obj: object) -> bool:
return isinstance(obj, (str, int, float, bool, type(None), bytes, list, dict)) \
or hasattr(obj, "model_dump") # pydantic Try / catch
try:
payload = encode(value)
except NotImplementedError as e:
logging.warning("unserializable value replaced: %s", e)
payload = encode(str(value)) Prevention
- Return Pydantic models or plain JSON-able data from serialized functions
- Register custom types with the serde allowlist before use
- Avoid nested containers holding arbitrary custom objects in stored results
When it happens
Trigger: Returning or storing an object of an unregistered custom class (e.g. arbitrary dataclass-like types, third-party objects) from a function whose result is serialized to msgpack — exercised directly by test_unregistered_nested_raises for nested unregistered values.
Common situations: Returning custom classes, numpy arrays beyond supported kinds, datetime-like third-party types, or nested containers holding unregistered objects through target-state or memo result serialization.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Unknown extension code: {code}
- Cannot deserialize msgspec payload ({_error_context()})
- Failed to deserialize msgspec payload ({_error_context()})
- Failed to deserialize pydantic payload ({_error_context()})
- Failed to deserialize pickle payload ({_error_context()})
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/c5fe116af314ba40.
Report an issue: GitHub.