Memory Troubleshooting
Common errors when configuring memory providers and how to fix them
Memory troubleshooting helps resolve common errors when configuring memory providers and debugging memory-related issues in PraisonAI agents.
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
instructions="Help the user remember things.",
memory=True,
)
agent.start("Remember that I prefer concise answers.")The user enables memory and hits a provider error; this guide maps common failures to fixes.
Quick Start
- Default (No Extras) — Works Out of the Box
python from praisonaiagents import Agent agent = Agent( name="Assistant", instructions="Help the user remember things", memory=True # Uses built-in file storage ) - Switch to Real Provider — Install Extras First
bash pip install "praisonaiagents[memory]"python from praisonaiagents import Agent agent = Agent( name="Assistant", instructions="Help the user remember things", memory="mem0" # Now uses Mem0 cloud service )
Why am I seeing ImportError: mem0ai is not installed...?
This error occurs when you explicitly request a memory provider that requires optional dependencies. The new behavior ensures you get clear feedback instead of silent fallbacks.
The Problem
# This will fail if mem0ai package is not installed
agent = Agent(memory="mem0")The Solution
Install the required extras package:
pip install "praisonaiagents[memory]"Explicit vs Default Behavior
| Configuration | mem0ai installed? | Result |
|---|---|---|
memory=True (default) | ❌ | ✅ Falls back to file storage |
memory="mem0" | ❌ | ❌ ImportError: mem0ai is not installed. Run: pip install 'praisonaiagents[memory]' |
memory="mem0" | ✅ | ✅ Uses Mem0 (if API key set) |
Why am I seeing ValueError: Mem0 API Key not provided?
This occurs when the mem0ai package is installed but the API key is missing.
Set the API Key
Environment Variable
export MEM0_API_KEY="your-mem0-api-key"Direct Configuration
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
memory={
"provider": "mem0",
"config": {
"api_key": "your-mem0-api-key"
}
}
)Why am I seeing TypeError: MemoryConfig.db must be a DbAdapter instance?
This error fires at agent construction when memory={"db": ...} (or MemoryConfig(db=...)) receives something that isn’t a real database adapter — most commonly a bare file-path string.
The Problem
from praisonaiagents import Agent
# ❌ Was silently broken before PR #5679 — now raises TypeError at construct
agent = Agent(memory={"db": "/tmp/sessions.db"})
# TypeError: MemoryConfig.db must be a DbAdapter instance (e.g. db(...) /
# db.SQLiteDB(path=...)) implementing the on_agent_start/on_user_message/
# on_agent_message hooks, not str. For a SQLite file use
# db(database_url="sqlite:///path/to.db") or
# MemoryConfig(backend="sqlite", config={"short_db": "short.db", "long_db": "long.db"}).Earlier releases accepted the string, warned on each hook call ('str' object has no attribute 'on_agent_start'), and silently dropped every message — memory looked enabled while no turns were ever stored. Fix landed in PR #5679 (fixes #5668).
Behavior change at a glance
| Input | Before PR #5679 | After PR #5679 |
|---|---|---|
memory={"db": "/path/x.db"} | Warning + silent persist loss | TypeError at construct |
memory=MemoryConfig(db="/path/x.db") | Warning + silent persist loss | TypeError at construct |
memory=MemoryConfig(db="") | Warning + silent persist loss | TypeError at construct |
memory=MemoryConfig(db=123) | Warning + silent persist loss | TypeError at construct |
memory=MemoryConfig(db=db(database_url="…")) | Works | Works (unchanged) |
memory=MemoryConfig(db=None) (default) | Works | Works (unchanged) |
The Fix
Pick one of the two supported shapes depending on how you want to point to a SQLite file (or any backing store):
db() factory with a URL
Use the db factory for URL-based stores. Works for sqlite, postgresql, and more.
from praisonaiagents import Agent, MemoryConfig, db
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
memory=MemoryConfig(db=db(database_url="sqlite:///tmp/sessions.db")),
)
agent.start("Remember my favourite colour is teal.")backend + config
Use backend="sqlite" and put file paths inside config={}. The config dict is the correct home for path strings — db= is for adapter instances only.
from praisonaiagents import Agent, MemoryConfig
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
memory=MemoryConfig(
backend="sqlite",
config={"short_db": "./mem/short.db", "long_db": "./mem/long.db"},
),
)
agent.start("Remember my favourite colour is teal.")Interaction flow
Why the hook check, not just a type check?
The memory bridge drives db through three hooks: on_agent_start, on_user_message, on_agent_message. A valid db is either a DbAdapter or a db(...) backend instance — both expose these hooks. The guard requires the hooks themselves (callable), not a weaker signal like database_url that a half-built object could expose while still dropping every message.
See also Database Persistence and Session Persistence for custom DbAdapter implementations.
Why is memory="mem0" returning empty search results? (MongoDB vector store)
Search results come back empty because mem0’s MongoDB vector store has an upstream signature-mismatch bug.
Symptom: Searches return [], and the logs contain Detected mem0 MongoDB vector store compatibility issue. (before this was surfaced, the adapter path returned empty results with no log at all).
Cause: mem0’s MongoDB vector store raises TypeError: unexpected keyword argument 'vectors' on .search() (mem0ai/mem0#3185); PraisonAI catches that specific TypeError, logs a warning, and returns [] so the agent keeps running. PraisonAI does not fix the upstream bug — the fix lives in mem0.
Both the memory-layer and the knowledge-layer mem0 search paths now delegate to the same safe_mem0_search helper in praisonaiagents.memory.adapters.factories, so this fallback behaviour is identical whether you configured mem0 via memory= or via knowledge=. Fix reference: PraisonAI PR #5204.
Fix: switch mem0’s vector store to Qdrant or Chroma
Qdrant
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
memory={
"provider": "mem0",
"config": {
"vector_store": {
"provider": "qdrant",
"config": {"host": "localhost", "port": 6333},
},
},
},
)Chroma
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
memory={
"provider": "mem0",
"config": {
"vector_store": {
"provider": "chroma",
"config": {"collection_name": "praisonai", "path": "./chroma_db"},
},
},
},
)Alternative: use PraisonAI’s built-in MongoDB adapter
If you need MongoDB itself, use PraisonAI’s first-party MongoDB Memory adapter — it is a separate implementation, unrelated to mem0, and unaffected by this bug.
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
memory={
"provider": "mongodb",
"config": {
"connection_string": "mongodb://localhost:27017/",
"database": "praisonai",
},
},
)See also the Mem0 integration guide.
My mem0 / mongodb config isn’t being used — retrieval feels like keyword search
On releases before 2026-07-14, Knowledge(config=...) could silently degrade a configured mem0 or mongodb backend to SQLite because the adapter constructor rejected an internal verbose keyword (PR #2982). Check which adapter you actually got:
from praisonaiagents import Knowledge
kb = Knowledge(config={
"vector_store": {
"provider": "mem0",
"config": {"collection_name": "my_docs"},
}
})
print(type(kb.memory).__name__) # 'Mem0Adapter' on the fix; 'SQLiteKnowledgeAdapter' means you're on a buggy release.If it isn’t Mem0Adapter / MongoDBKnowledgeAdapter, upgrade to a release built after commit 69d7ecf. On the fixed release, an explicit provider that fails to construct emits a WARNING naming the provider and the reason:
Knowledge provider '<name>' failed to initialize (<reason>); falling back to a different backend. Retrieval quality may be reduced.See Knowledge Backends → Troubleshooting: silent SQLite fallback for the full walkthrough.
Memory silently returned empty context
On releases before PR #4213, Agent(memory=True) retrieved memory hits but only included them in the task prompt when the root logger was at DEBUG. Under normal WARNING/INFO logging the retrieved context was logged and then discarded, so nothing reached the LLM.
Old workaround (no longer needed): enabling verbose=5 / DEBUG logging, or calling agent.memory.build_context_for_task(..., include_in_output=True) by hand.
Now: retrieval reaches the prompt by default — build_context_for_task() defaults include_in_output=True, and agent.memory.get_context(query=...) returns the prompt-ready string for the non-prompt-caching path.
from praisonaiagents import Agent
agent = Agent(name="Assistant", instructions="Help the user.", memory=True)
agent.memory.remember("User prefers metric units.")
# Reaches the prompt under normal logging — no DEBUG required
print(agent.memory.get_context(query="What units do I prefer?"))My second Agent instance doesn’t recall what the first one said (auto_memory + prefetch + user_id)
A new Agent with the same user_id and prefetch=True answers as if a fact stored by an earlier instance was never saved — no errors, no warnings.
Symptom: Agent A stores a fact via auto_memory=True and a shared user_id; a new Agent B with the same user_id and prefetch=True answers as if the fact were never stored.
Cause: Fixed by PR #5688. On earlier releases, auto-memory wrote only to short-term memory with no user_id in record metadata, and turn-start prefetch queries long-term with a metadata.user_id post-filter — so every persisted row was silently dropped on recall.
Fix: upgrade to a build containing PR #5688 (merged into main 2026-10-07, head 9f1c205f). On the fix, auto_memory=True persists each turn to long-term memory stamped with the configured user_id / session_id, so the prefetch scope filter matches.
Verify recall works end to end:
from praisonaiagents import Agent, MemoryConfig
shared = dict(backend="sqlite", user_id="alice", auto_memory=True)
Agent(
name="writer",
instructions="You help the user.",
memory=MemoryConfig(**shared),
).start("Remember codename ORANGE-PANDA for me.")
reader = Agent(
name="reader",
instructions="Answer using recalled context.",
memory=MemoryConfig(**shared, prefetch=True),
)
answer = reader.start("What's my codename?")
assert "ORANGE-PANDA" in answer # recalled block is non-empty on the fixIsolation holds: a different user_id does not recall another user’s turn.
See Memory Prefetch → Automatic cross-instance recall and Memory → Always set user_id.
My agent.store_memory() fact never reaches the model (sqlite / chroma / mem0)
agent.store_memory("…", memory_type="long_term") returns, logs show the row persisted, and the next agent.chat(...) answers as if the fact were never saved.
Symptom: On memory="sqlite" (and "chroma", "mem0", {"provider": ...}), store_memory writes a long-term row but a follow-up question answers “I don’t know”.
Cause: Fixed by PR #6058. On earlier releases:
- Turn-start prefetch was off by default (
prefetch=False), so the backend was never queried with the user prompt. Memory.store_long_term/store_short_termdidn’t stampmetadata["user_id"], so even with prefetch forced on, the user-scoped post-filter dropped the row.Memory.get_context()‘s empty-query guard (deliberately) returns""to avoid cross-user leakage, so the system prompt had no stored facts either.
Fix: upgrade to a build containing PR #6058 (merged 2026-10-28, head 9fe98816). On the fix, MemoryConfig.prefetch defaults to None (“auto”) and runs for query-based backends automatically, and store_long_term / store_short_term stamp the store’s user_id into metadata so recall matches. An explicit metadata["user_id"] still wins.
Verify:
from praisonaiagents import Agent
agent = Agent(name="A", instructions="Answer briefly.", memory="sqlite")
agent.store_memory("The project codename is BLUEHERON.", memory_type="long_term")
answer = agent.chat("What is the project codename?")
assert "BLUEHERON" in answer # recalled on the fix, missing beforeStill missing on the fix? Check the logs for Falling back to FileMemory. If the backend’s dependencies are missing or it can’t initialise (e.g. mem0 without credentials), the agent uses FileMemory instead, and auto prefetch is off for FileMemory. Install the backend’s extra, or pass prefetch=True.
Overrides still work: MemoryConfig(backend="sqlite", prefetch=False) turns prefetch off for cost reasons, and MemoryConfig(prefetch=True) forces it on even for FileMemory. See Memory Prefetch.
My AutoMemory preview blocked a later store (store=False then store=True wrote nothing)
A process_interaction(..., store=False) preview marked the interaction as processed, so a follow-up store=True for the same text returned [] and persisted nothing.
Symptom: auto.process_interaction(text, store=False) returns extracted memories; a follow-up auto.process_interaction(text, store=True) returns [] and nothing is persisted in FileMemory.
Cause: Fixed by PR #5689. On earlier releases, process_interaction recorded the interaction hash before calling _store_memories, so a store=False preview marked the text as already processed and blocked the real store. The same bug left the hash consumed after a failed store, preventing retry once the backend recovered.
Fix: upgrade to a build containing PR #5689 (merged into main 2026-10-08, head 1cebaa0e). On the fix, a preview never consumes dedup and the hash is recorded only after a successful write.
Verify the preview no longer blocks a real store:
from praisonaiagents.memory import FileMemory, AutoMemory
base = FileMemory(user_id="user123")
auto = AutoMemory(base, enabled=True)
auto.process_interaction("I prefer concise answers.", store=False)
stored = auto.process_interaction("I prefer concise answers.", store=True)
assert stored, "preview should not block a later real store on PR #5689"Related symptom: a retry after a transient backend outage stores nothing. Same root cause, same fix — see Previews and retry semantics.
Why did my metadata dict come back as a string? (or: my None values disappeared)
The chroma / rag (default) memory backend only accepts primitive metadata values, so non-primitives are coerced to str(...) and None values are dropped.
Cause: ChromaDB rejects non-primitive metadata (str, int, float, bool only). PraisonAI coerces dict / list / other types to str(...), and drops None values, so the ChromaDB write never fails.
Fix (if you need round-trippable structured metadata): serialise it yourself with json.dumps(...) into a str field, or switch to a metadata-native backend like mongodb, mem0, or dakera.
import json
from praisonaiagents import Memory
memory = Memory(config={"provider": "rag"})
# Instead of a raw dict/list (which gets stringified), store JSON in a str field
memory.store_long_term(
text="Project atlas kicked off",
metadata={"tags_json": json.dumps(["backend", "urgent"])}, # round-trips cleanly
)See Metadata types (ChromaDB / RAG backend) for the full coercion table.
Common Error Scenarios
User Interaction Flow
Step-by-Step Resolution
- User runs
Agent(memory="mem0")without extras - PraisonAI raises
ImportError: mem0ai is not installed. Run: pip install 'praisonaiagents[memory]' - User runs the suggested install command
- User re-runs the agent code — either works or shows next error (missing API key)
- User sets
MEM0_API_KEYenvironment variable - Agent works successfully
Dakera adapter not loading
Dakera adapter not loading
Symptom: ImportError when using memory="dakera" or memory={"provider": "dakera", ...}.
Install the extra:
pip install "praisonaiagents[dakera]"Or equivalently:
pip install dakeraThe exact error message when the package is missing:
dakera is required for the dakera adapter. Install with: pip install 'praisonaiagents[dakera]' (or: pip install dakera)Explicit provider now raises immediately: Using provider="dakera" raises this ImportError with the install hint instead of silently falling back to SQLite.
If the server is unreachable: Ensure Dakera is running at the configured URL (default http://localhost:3000). See dakera-ai/dakera-deploy for Docker Compose setup.
SQLite memory: errors after upgrade
ValueError: Invalid table name
AttributeError: missing connection helper
Dakera Adapter Not Loading
Dakera adapter not loading: ImportError
Symptom: Running with provider="dakera" raises:
ImportError: dakera is required for the dakera adapter. Install with: pip install 'praisonaiagents[dakera]' (or: pip install dakera)Fix: Install the Dakera extra:
pip install "praisonaiagents[dakera]"This error surfaces because explicit provider="dakera" now raises a helpful hint instead of silently falling back to SQLite (fix landed in PR #2591 follow-up commit bbddfe3e).
My other agent’s memory disappeared when I called reset_long_term()
Older builds reset long-term memory by wiping every collection in the shared Chroma persistent directory, so calling reset_long_term() on one agent also erased sibling agents that shared the same path.
reset_long_term() now deletes only this instance’s own collection and re-initializes it — other agents sharing the same rag_db_path keep their data. A failed reset also raises now instead of silently reporting success.
Give each agent a distinct collection_name when they share a persistent path so resets stay isolated:
from praisonaiagents import Agent
agent = Agent(
name="Researcher",
memory={
"provider": "rag",
"rag_db_path": "./chroma_db",
"collection_name": "researcher_ltm", # default is "memory_store"
},
)See Memory Configuration → Chroma Collection Name.
Best Practices
Start with the default, upgrade later
Begin with memory=True for prototyping, then switch to memory="mem0" for production when you need advanced features.
Pin extras in your project
Add "praisonaiagents[memory]" to your requirements.txt or pyproject.toml to ensure consistent environments.
Set keys via environment variables in production
Use MEM0_API_KEY environment variables rather than hardcoding API keys in your source code.
Use memory=True for prototypes
The default file-based memory works great for development and doesn’t require any external dependencies or API keys.
Related
Understanding different types of memory and storage options
Advanced MemoryMulti-tiered memory with quality scoring and graph support
Dakera MemorySelf-hosted, decay-weighted vector recall via the Dakera server.
Memory ConsolidationMerge, promote, and prune memories under a loss-bounded guard.