{"record":{"id":"c5fe116af314ba40","repo":"cocoindex-io/cocoindex","slug":"cannot-serialize-type-obj-name","errorCode":null,"errorMessage":"Cannot serialize {type(obj).__name__}","messagePattern":"Cannot serialize (.+?)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/serde.py","lineNumber":281,"sourceCode":"\n\n# ---------------------------------------------------------------------------\n# Serialization hooks (cross-pollination bridge)\n# ---------------------------------------------------------------------------\n\n\ndef _enc_hook(obj: Any) -> Any:\n    \"\"\"Msgspec enc_hook: handles types msgspec can't encode natively.\"\"\"\n    # C: Quarantine pickle types (check first — explicit opt-in wins)\n    if type(obj) in _SERIALIZE_BY_PICKLE_TYPES:\n        return msgspec.msgpack.Ext(100, _strict_pickle_dumps(obj))\n    key = (type(obj).__module__, type(obj).__qualname__)\n    if key in _UNPICKLE_SAFE_GLOBALS:\n        return msgspec.msgpack.Ext(100, _strict_pickle_dumps(obj))\n    # B: Bridge Pydantic into msgspec\n    if _is_pydantic_instance(obj):\n        return obj.model_dump(mode=\"json\")\n    raise NotImplementedError(f\"Cannot serialize {type(obj).__name__}\")\n\n\n_msgspec_encoder = msgspec.msgpack.Encoder(enc_hook=_enc_hook)\n\n\n# ---------------------------------------------------------------------------\n# Deserialization hooks\n# ---------------------------------------------------------------------------\n\n\ndef _ext_hook(code: int, data: memoryview) -> Any:  # type: ignore[type-arg]\n    \"\"\"Un-quarantine pickle inside msgspec payloads.\"\"\"\n    if code == 100:\n        return _RestrictedUnpickler(io.BytesIO(bytes(data))).load()\n    raise ValueError(f\"Unknown extension code: {code}\")\n\n\ndef _dec_hook(type_hint: Any, obj: Any) -> Any:","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/serde.py#L263-L299","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nreturn MyCustomClass(x=1)  # NotImplementedError from _enc_hook\n\n// after\nfrom pydantic import BaseModel\nclass Result(BaseModel):\n    x: int\nreturn Result(x=1)  # serialized via model_dump","handlingStrategy":"try-catch","validationCode":"def is_serializable(obj: object) -> bool:\n    from cocoindex._internal import serde\n    key = (type(obj).__module__, type(obj).__qualname__)\n    return key in serde._UNPICKLE_SAFE_GLOBALS or serde._is_pydantic_instance(obj)","typeGuard":"def is_encodable(obj: object) -> bool:\n    return isinstance(obj, (str, int, float, bool, type(None), bytes, list, dict)) \\\n        or hasattr(obj, \"model_dump\")  # pydantic","tryCatchPattern":"try:\n    payload = encode(value)\nexcept NotImplementedError as e:\n    logging.warning(\"unserializable value replaced: %s\", e)\n    payload = encode(str(value))","preventionTips":["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"],"tags":["python","serialization","msgpack"],"backgroundTag":"json-serialization-failed","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}