Repository navigation
Description
Component
Vector Store
Summary
Langchain.list() (mem0/vector_stores/langchain.py:196) gates every return behind hasattr(self.client, "_collection"). For any langchain VectorStore that is not Chroma-backed (FAISS, Qdrant, PGVector, ...), the function falls off the end and returns None — not even []. LangchainConfig.client accepts any existing VectorStore instance, so non-Chroma clients are a supported configuration, and every one of them breaks Memory.get_all() and Memory.delete_all():
Memory.get_all()iterates the result atmem0/memory/main.py:1354(for mem in actual_memories:) →TypeError: 'NoneType' object is not iterableMemory.delete_all()indexes it atmem0/memory/main.py:1923-1925(self.vector_store.list(filters=filters, top_k=DELETE_ALL_BATCH_SIZE)[0]) →TypeError: 'NoneType' object is not subscriptable
Steps to Reproduce
Fully offline (no API key, no network; FakeEmbeddings avoids any model calls):
from langchain_community.vectorstores import FAISS
from langchain_core.embeddings import FakeEmbeddings
from mem0 import Memory
faiss_store = FAISS.from_texts(["hello", "world"], embedding=FakeEmbeddings(size=8))
print("FAISS store has '_collection' attr:", hasattr(faiss_store, "_collection"))
config = {
"vector_store": {
"provider": "langchain",
"config": {"client": faiss_store, "collection_name": "mem0"},
},
"embedder": {"provider": "openai",
"config": {"api_key": "dummy", "embedding_dims": 1536}},
"llm": {"provider": "openai",
"config": {"api_key": "dummy", "model": "gpt-4o-mini"}},
}
m = Memory.from_config(config)
print("vector_store.list() returns:", m.vector_store.list())
try:
m.get_all(filters={"user_id": "alice"})
print("get_all(): succeeded")
except Exception as e:
print(f"get_all() raised {type(e).__name__}: {e}")
try:
m.delete_all(user_id="alice")
print("delete_all(): succeeded")
except Exception as e:
print(f"delete_all() raised {type(e).__name__}: {e}")
# control: a real Chroma client through the same Langchain wrapper
import chromadb
from langchain_community.vectorstores import Chroma
print()
print("=== control: real Chroma client through the same Langchain store ===")
chroma_store = Chroma(collection_name="mem0",
embedding_function=FakeEmbeddings(size=8),
client=chromadb.EphemeralClient())
print("Chroma store has '_collection' attr:", hasattr(chroma_store, "_collection"))
m2 = Memory.from_config({**config, "vector_store": {
"provider": "langchain",
"config": {"client": chroma_store, "collection_name": "mem0"}}})
print("vector_store.list() returns:", m2.vector_store.list())
print("get_all():", m2.get_all(filters={"user_id": "alice"}))
print("delete_all() count:", m2.delete_all(user_id="alice"))Expected Behavior
list() returns a (nested) list for every client, as VectorStoreBase.list() documents ("List all memories", mem0/vector_stores/base.py:59-61) and as every sibling implementation does — faiss.py:619, cassandra.py:474, opensearch.py:406, mongodb.py:410 all return a nested list even when empty. With that, get_all() returns {'results': []} and delete_all() completes, exactly as the Chroma control group does.
Actual Behavior
Actual output (mem0 2.0.20 from source @ c7ee362a, Python 3.12.14, macOS; langchain 1.4.2, langchain-community 0.4.2, faiss-cpu 1.15.1, chromadb 1.5.9):
FAISS store has '_collection' attr: False
vector_store.list() returns: None
get_all() raised TypeError: 'NoneType' object is not iterable
delete_all() raised TypeError: 'NoneType' object is not subscriptable
=== control: real Chroma client through the same Langchain store ===
Chroma store has '_collection' attr: True
vector_store.list() returns: [[]]
get_all(): {'results': []}
delete_all() count: {'message': 'Memories deleted successfully!'}
The tracebacks land at mem0/memory/main.py:1354 (for mem in actual_memories: in get_all) and mem0/memory/main.py:1925 (the )[0] in delete_all).
Environment
- mem0 version: 2.0.20 (from source, main @
c7ee362a) - Python 3.12.14, macOS (darwin, arm64)
- langchain 1.4.2, langchain-community 0.4.2, faiss-cpu 1.15.1, chromadb 1.5.9
How You Verified This
What I Ran
The exact script above, offline: a FAISS VectorStore built locally with FakeEmbeddings, wrapped in Memory via vector_store.provider = "langchain"; then the same wrapper around a real (ephemeral) Chroma client as a control.
What I Saw
The verbatim output pasted in "Actual Behavior" above: list() returns None on the FAISS client, get_all() raises TypeError: 'NoneType' object is not iterable, delete_all() raises TypeError: 'NoneType' object is not subscriptable; the Chroma control returns [[]] and both methods succeed.
Why This Is a Bug
VectorStoreBase.list()'s contract is "List all memories" (mem0/vector_stores/base.py:59-61), and the consumers in main.py assume a list. Every sibling vector store returns a nested list even when empty (faiss.py:619, cassandra.py:474, opensearch.py:406, mongodb.py:410). LangchainConfig.client is typed as "Existing VectorStore instance" — any langchain VectorStore, not only Chroma — so the non-Chroma path is supported configuration, and it returns None.
What I Ruled Out
- Not a FAISS-specific quirk: the gate is
hasattr(self.client, "_collection"), so any non-Chroma langchain client (Qdrant, PGVector, ...) takes the same fall-through; only the Chroma-backed client has_collection. - Not the
exceptbranch: for a non-Chroma client thetryblock completes without raising — the function simply has noreturnleft on that path. - Not caller misuse: the config path used is the documented
provider: "langchain"+clientwiring, and the identical wiring with a Chroma client works.
The fix direction: the non-Chroma path should return [[]] (the sibling convention; a flat [] would still make delete_all()'s unconditional [0] at main.py:1925 raise IndexError). With that one-line change I re-ran the script: list() returns [[]], get_all() returns {'results': []}, delete_all() succeeds, and tests/vector_stores/test_langchain_vector_store.py passes (15 passed, including a regression test for this).
Happy to be assigned — I can open a PR once this issue carries the accepted label.
AI Assistance
AI found and wrote this, and I have not reproduced it myself. That said, the reproduction above is a self-contained offline script (no credentials, no network) and its output is pasted verbatim, so it can be re-run directly.
Activity
BlueX888 commentedon Sep 24, 2026
Reproduced this. Root cause: mem0/vector_stores/langchain.py:196 gates every return behind hasattr(client,'_collection'); non-Chroma clients fall through to implicit None
Minimal reproduction:
Observed output:
Happy to open a PR with this fix, or to be assigned if you prefer to take it.
O96a commentedon Sep 24, 2026
That's a real bug — the
hasattr(self.client, "_collection")gate only ever matches Chroma's wrapper, so FAISS/Qdrant/PGVector skip every branch and return implicitNone. Proper fix is to drop the gate and dispatch on the actual client type; until that lands, call the underlying store directly (client.index.scroll()for Qdrant,client.similarity_search("")for FAISS) instead of going throughMemory.get_all()/delete_all().YS-OH-CORE commentedon Sep 25, 2026
A nonempty matching-data regression is important before adopting the proposed
return [[]]: it removes the exception but can make deletion falsely report success.I tested that fallback at
989c7da0with realMemorymethods and a real LangChain FAISS store containing six Alice documents and one Bob document:The actual call uses
get_all(filters={'user_id': ...}). I checked retained records by known IDs and content, not through the brokenlist()path.Memory.get(known_id)still returned the target. As a positive control,Memory.delete(known_id)removed exactly that record and left Bob untouched. A truly empty store produces the same empty/success responses under the fallback, so an empty-only test misses the distinction.Executed checker, observations and limits · completed run.
A fix should implement correct scoped enumeration or explicitly report unsupported enumeration, rather than invent an empty result. An unsupported-operation error must also avoid being swallowed by the method's broad
except. The suggested FAISSsimilarity_search('')is not exhaustive either: the defaultk=4returned four of the six matching documents here.Scope: real constructor/adapter/FAISS and temporary history; unused LLM/embedder factories and notice callbacks were test doubles. No credentials, model requests, Chroma test, or full upstream suite. The error variant was a design control, not a proposed complete patch. Your original fall-through diagnosis remains valid.
Check and execution by Zero, an AI collaborator with Youngseok Oh (@YS-OH-CORE).
fix(vector_stores): raise NotImplementedError from Langchain.list() f…
Souptik96 commentedon Sep 26, 2026
Thanks @YS-OH-CORE for the populated-store check: you're right that a
[[]]fallback turns the crash into a silent false success. I've updated #7464 soLangchain.list()raisesNotImplementedErrorfor non-Chroma clients (outside the broadexcept), and Chroma listing errors now propagate instead of returning an empty result. There's a regression test with a real FAISS store holding matching records:delete_all()raises and every record stays in place. Could a maintainer take a look and consider labelling thisaccepted?YS-OH-CORE commentedon Sep 26, 2026