run-llama/llama_index · error · ValueError
Objs is not pickleable
Error message
Objs is not pickleable
What it means
SimpleObjectNodeMapping.persist pickles the whole mapping (self, including every object) to <persist_dir>/object_node_mapping.pkl. If any object is not pickleable, pickle.PickleError is re-raised as ValueError('Objs is not pickleable'). Common unpickleable values include lambdas/closures, open file/socket/DB-engine handles, and objects holding thread locks.
Source
Thrown at llama-index-core/llama_index/core/objects/base_node_mapping.py:207
def persist(
self,
persist_dir: str = DEFAULT_PERSIST_DIR,
obj_node_mapping_fname: str = DEFAULT_PERSIST_FNAME,
) -> None:
"""
Persist object node mapping.
NOTE: This may fail depending on whether the object types are
pickle-able.
"""
if not os.path.exists(persist_dir):
os.makedirs(persist_dir)
obj_node_mapping_path = concat_dirs(persist_dir, obj_node_mapping_fname)
try:
with open(obj_node_mapping_path, "wb") as f:
pickle.dump(self, f)
except pickle.PickleError as err:
raise ValueError("Objs is not pickleable") from err
@classmethod
def from_persist_dir(
cls,
persist_dir: str = DEFAULT_PERSIST_DIR,
obj_node_mapping_fname: str = DEFAULT_PERSIST_FNAME,
) -> "SimpleObjectNodeMapping":
obj_node_mapping_path = concat_dirs(persist_dir, obj_node_mapping_fname)
try:
with open(obj_node_mapping_path, "rb") as f:
simple_object_node_mapping = _RestrictedUnpickler(f).load()
except pickle.PickleError as err:
raise ValueError("Objs cannot be loaded.") from err
return simple_object_node_mapping
View on GitHub (pinned to afd0fef371)
Solutions
- Remove non-pickleable attributes from stored objects (e.g. detach the engine/client, implement __getstate__/__setstate__ to drop it)
- Replace lambdas with module-level functions or functools.partial over pickleable args
- Use a custom BaseObjectNodeMapping subclass that persists only what it needs (e.g. store tool names/configs) instead of the whole object
- Skip mapping persistence and rebuild the ObjectIndex from objects at load time, passing object_node_mapping to ObjectIndex.from_persist_dir
Example fix
# before
@dataclass
class Doc:
name: str
session: requests.Session # not pickleable -> ValueError: Objs is not pickleable
# after
@dataclass
class Doc:
name: str
session: Optional[requests.Session] = None
def __getstate__(self):
state = self.__dict__.copy()
state["session"] = None # drop live handle before pickling
return state Defensive patterns
Strategy: validation
Validate before calling
import pickle test = pickle.dumps(mapping) # dry-run picklability before persisting to disk
Type guard
def is_pickleable(obj) -> bool:
import pickle
try:
pickle.dumps(obj)
return True
except (pickle.PickleError, TypeError, AttributeError):
return False Try / catch
try:
mapping.persist(persist_dir)
except ValueError as e:
if "not pickleable" in str(e):
# fall back: persist index only, rebuild mapping from objects at load time
obj_index.index.storage_context.persist(persist_dir=persist_dir)
else:
raise Prevention
- Keep persisted objects as plain data (dataclasses/dicts of primitives)
- Exclude live handles via __getstate__ (return a copy of __dict__ minus the handle)
- Never store lambdas/closures in objects meant to be persisted
When it happens
Trigger: Calling obj_index.persist(persist_dir) (or mapping.persist) on a SimpleObjectNodeMapping whose objects list contains lambdas, SQLAlchemy engines/sessions, LangChain tools wrapping non-pickleable callables, or objects with __slots__ misconfigured / __reduce__ raising.
Common situations: ObjectIndex built over QueryEngineTool objects that capture a live LLM/embeddings client; objects holding a requests.Session or cuda tensors; persisting in notebooks where objects are closures; switching from plain dataclasses to ones holding a client object.
Related errors
- Unable to load from persist dir. The object_node_mapping can
- Objs cannot be loaded.
- Embedding loading requires a class_name
- FnNodeMapping does not support persist method.
- This object node mapping does not support persist method.
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/a54c11610987fd4d.
Report an issue: GitHub.