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
- Pass only Serializable/JSON-native values to dumps; store non-serializable objects outside serialized fields or as serializable identifiers
- If the object is pydantic but not Serializable, convert it to a dict first (e.g. obj.model_dump())
- 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
- Never store live clients, tokenizers, or arbitrary SDK objects in fields that get dumped
- Convert pydantic models with .model_dump() before nesting them into dumps inputs
- Run dumps() in a smoke test for every object type you persist
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
- `default` should not be passed to dumps
- Unable to get string for blob {self}
- Unable to get bytes for blob {self}
- Failed to hash metadata: {e}. Please use a dict that can be
- Vectorstore should be either a VectorStore or a DocumentInde
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/0afd4ca1d1a19718.
Report an issue: GitHub.