run-llama/llama_index · error · ValueError
Must provide either user_msg or chat_history
Error message
Must provide either user_msg or chat_history
What it means
StorageContext.to_dict (used when serializing an entire index to a JSON/dict payload) requires that every store it holds is the in-memory 'simple' implementation: SimpleDocumentStore, SimpleIndexStore, SimpleGraphStore, SimplePropertyGraphStore (or None), and SimpleVectorStore for all vector stores. Any custom or database-backed store makes all_simple False and raises this ValueError, because only the simple stores have a JSON-serializable format.
Source
Thrown at llama-index-core/llama_index/core/agent/workflow/base_agent.py:429
)
await ctx.store.set("user_msg_str", content_str)
elif chat_history and not all(
message.role == "system" for message in chat_history
):
# If no user message, use the last message from chat history as user_msg_str
user_hist: List[ChatMessage] = [
msg for msg in chat_history if msg.role == "user"
]
content_str = "\n".join(
[
block.text
for block in user_hist[-1].blocks
if isinstance(block, TextBlock)
]
)
await ctx.store.set("user_msg_str", content_str)
else:
raise ValueError("Must provide either user_msg or chat_history")
# Get all messages from memory
input_messages = await memory.aget()
# send to the current agent
return AgentInput(input=input_messages, current_agent_name=self.name)
@step
async def setup_agent(self, ctx: Context, ev: AgentInput) -> AgentSetup:
"""Main agent handling logic."""
llm_input = [*ev.input]
if self.system_prompt:
llm_input = [
ChatMessage(role="system", content=self.system_prompt),
*llm_input,
]
View on GitHub (pinned to afd0fef371)
Solutions
- Persist each store through its own backend instead of to_dict: leave data in the vector DB / docstore and persist only index_struct via index_store, or use index.persist(persist_dir) per-store.
- If you need to_dict, construct the StorageContext entirely from simple stores (StorageContext.from_defaults()) and move data into external backends separately.
- Serialize only what is serializable: save index structures with SimpleIndexStore and keep documents/vectors in their dedicated stores.
- Check isinstance on each store before calling to_dict and raise a clearer domain-specific error in your own code.
Example fix
# before
sc = StorageContext.from_defaults(vector_store=chroma_store)
index.set_index_store(sc.index_store)
payload = sc.to_dict() # ValueError: to_dict only available when using simple ...
# after
# keep Chroma for vectors; persist only the simple index store
sc = StorageContext.from_defaults()
index = VectorStoreIndex(nodes, storage_context=sc, vector_store=chroma_store)
index.storage_context.index_store.persist("./storage/index_store.json") Defensive patterns
Strategy: validation
Validate before calling
from llama_index.core.storage.docstore import SimpleDocumentStore
from llama_index.core.storage.index_store import SimpleIndexStore
from llama_index.core.storage.graph_store import SimpleGraphStore
from llama_index.core.vector_stores import SimpleVectorStore
sc = storage_context
ok = (isinstance(sc.docstore, SimpleDocumentStore)
and isinstance(sc.index_store, SimpleIndexStore)
and isinstance(sc.graph_store, SimpleGraphStore)
and all(isinstance(v, SimpleVectorStore) for v in sc.vector_stores.values()))
if ok:
payload = sc.to_dict()
else:
payload = None # persist per-store instead Type guard
def storage_context_is_simple(sc) -> bool:
simple = (SimpleDocumentStore, SimpleIndexStore, SimpleGraphStore)
return (isinstance(sc.docstore, SimpleDocumentStore)
and isinstance(sc.index_store, SimpleIndexStore)
and isinstance(sc.graph_store, SimpleGraphStore)
and all(isinstance(v, SimpleVectorStore) for v in sc.vector_stores.values())) Try / catch
try:
payload = sc.to_dict()
except ValueError as e:
if "simple doc/index/vector stores" in str(e):
# fall back to per-store persistence
... Prevention
- Decide serialization strategy before swapping in external vector stores.
- Persist index_struct via the index store and data via each backend's own durability.
- Assert store types in a startup check when to_dict/save_to_string is part of the pipeline.
When it happens
Trigger: Building a StorageContext with e.g. ChromaVectorStore, MongoDocumentStore, or RedisKVStore-backed stores and then calling index.storage_context.to_dict() or index.save_to_string()/'index_json' paths that depend on it; calling to_dict after StorageContext.from_defaults(vector_store=custom_store).
Common situations: Starting with default simple stores, later swapping in a production vector DB (Milvus, Qdrant, Weaviate) via storage_context, then still trying index.save_to_dict / save_to_string; attempting to persist the whole context while using PropertyGraphIndex with Neo4j; serialization paths in workflows that assume simple stores.
Related errors
- First argument to Readability constructor should be a docume
- Command failed: {command} {result.stderr}
- Cannot initialize from a vector store that does not store te
- Vector store query result should return at least one of node
- No nodes returned by vector_query
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/ab3fb5660e13575d.
Report an issue: GitHub.