langchain-ai/langchain · error · TypeError

Expected Serializable, got {type(obj)}

Error message

Expected Serializable, got {type(obj)}

What it means

Raised by langchain_core.load._validation when attempting to serialize an object that is not an instance of Serializable. Only Serializable objects (which implement to_json) can be dumped by dumps/dumpd; arbitrary Python objects, plain dicts of non-serializable values, or pydantic models outside the Serializable hierarchy are rejected before reaching the JSON encoder.

Source

Thrown at libs/core/langchain_core/load/_validation.py:148

        obj: The `Serializable` object to serialize.

    Returns:
        The serialized dict with user data in kwargs escaped as needed.

    Note:
        Kwargs values are processed with `_serialize_value` to escape user data
        (like metadata) that contains `'lc'` keys. Secret fields are identified
        by the class's declared `lc_secrets` and skipped because `to_json()`
        already converted their values to secret markers.

        The check is key-based rather than shape-based. A shape-based check
        ("this dict looks like a secret marker") can be forged by user data,
        letting attacker-controlled free-form dicts bypass escaping and reach
        the Reviver.
    """
    if not isinstance(obj, Serializable):
        msg = f"Expected Serializable, got {type(obj)}"
        raise TypeError(msg)

    serialized: dict[str, Any] = dict(obj.to_json())

    # Process kwargs to escape user data that could be confused with LC objects.
    # Skip kwargs declared as secrets - `to_json()` already replaced their
    # values with secret markers via `_replace_secrets`.
    if serialized.get("type") == "constructor" and "kwargs" in serialized:
        secret_keys = _get_secret_keys(obj)
        serialized["kwargs"] = {
            k: v if k in secret_keys else _serialize_value(v)
            for k, v in serialized["kwargs"].items()
        }

    return serialized


def _unescape_value(obj: Any) -> Any:
    """Unescape a value, processing escape markers in dict values and lists.

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass only Serializable/JSON-native values to dumps; store non-serializable objects outside serialized fields or as serializable identifiers
  2. If the object is pydantic but not Serializable, convert it to a dict first (e.g. obj.model_dump())
  3. For truly custom classes, subclass langchain_core.load.serializable.Serializable and implement to_json

Example fix

# before
from langchain_core.load import dumps
dumps({'retriever': custom_retriever_obj})
# after
from langchain_core.load import dumps
dumps({'retriever_name': custom_retriever_obj.name})
Defensive patterns

Strategy: type-guard

Validate before calling

from langchain_core.load.serializable import Serializable
def assert_serializable_tree(o: object) -> None:
    if isinstance(o, dict):
        for v in o.values(): assert_serializable_tree(v)
    elif isinstance(o, (list, tuple)):
        for v in o: assert_serializable_tree(v)
    elif o is not None and not isinstance(o, (str, int, float, bool, Serializable)):
        raise TypeError(f'not serializable: {type(o)!r}')

Type guard

from langchain_core.load.serializable import Serializable
def is_serializable(o: object) -> bool:
    return o is None or isinstance(o, (str, int, float, bool, Serializable)) or hasattr(o, 'to_json')

Try / catch

try:
    dumps(obj)
except TypeError as e:
    if 'Expected Serializable' in str(e):
        obj = strip_or_convert(obj)  # replace offending values with dicts/primitives
        dumps(obj)
    else:
        raise

Prevention

When it happens

Trigger: dumps({'model': SomePydanticModel(...)}) where the model does not extend Serializable; dumps(some_custom_object); nesting a plain object inside otherwise-serializable kwargs. Note pydantic models are first converted by _dump_pydantic_models, so the failure is specific to non-pydantic, non-Serializable objects.

Common situations: Trying to serialize a third-party object (e.g. an SDK client or tokenizer) stored on a chain; mixing LangChain serialization (dumps) with generic JSON dumping expectations; version upgrades where a class stopped inheriting Serializable.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/0afd4ca1d1a19718. Report an issue: GitHub.