Repository navigation
add() returns event: ADD for memories the vector store never persisted #6911
Description
Component
Python SDK
Description
Summary
When a batch insert into the vector store fails, _add_to_vector_store retries record-by-record. Records that also fail the retry are logged and skipped — but the returned payload, the history rows, and entity linking are all still built from the full extracted set. Callers receive {"id": ..., "event": "ADD"} for memories that were never stored, and get() on those ids later returns nothing.
Affects both Memory and AsyncMemory.
Steps to Reproduce
from mem0 import Memory
m = Memory()
# Simulate a store that rejects one record: batch insert fails,
# then one record also fails the per-record retry.
real_insert = m.vector_store.insert
POISON = "User is allergic to penicillin"
def flaky_insert(vectors, ids, payloads):
if len(ids) > 1:
raise RuntimeError("batch insert rejected")
if payloads[0].get("data") == POISON:
raise RuntimeError("record rejected by vector store")
return real_insert(vectors=vectors, ids=ids, payloads=payloads)
m.vector_store.insert = flaky_insert
result = m.add(
[{"role": "user", "content": f"My name is Aryan. {POISON}. I work as an engineer."}],
user_id="u1",
)
for r in result["results"]:
print(r["event"], r["id"], repr(r["memory"]), "| in store:", m.vector_store.get(r["id"]) is not None)Expected Behavior
Only memories that actually persisted are returned as ADD. A record the store rejected should not appear in the results, should not get an ADD history row, and should not be referenced by linked_memory_ids in the entity store. If nothing persists at all, the call should raise VectorStoreError — which add()'s docstring already documents but nothing currently raises.
Actual Behavior
All three extracted memories are returned as successful ADDs while only two exist in the store. The failure surfaces only as a log line, at the same moment the call reports success.
ERROR mem0.memory.main: Failed to insert memory 330d01bf-...: record rejected by vector store
add() reported 3 memories as persisted:
ADD c0196d4e "User's name is Aryan" | in store: True
ADD 330d01bf 'User is allergic to penicillin' | in store: False <-- phantom
ADD 6d26dded 'User works as an engineer' | in store: True
vector store actually holds 2 records
No exception is raised. The history table also gains an ADD row for the phantom id, and entity linked_memory_ids point at a memory that does not exist.
Source: mem0/memory/main.py — fallback loop at L1051 (sync) / L2704 (async); results built from the unfiltered records at L1190 / L2842.
Environment
- mem0 version: 2.0.17
- Python/Node version: Python 3.11
- OS: Windows 11
Activity
Diwak4r commentedon Aug 22, 2026
Maintainer triage request (per the new PR-gate policy): I have a fix ready for this in #7066, and it will auto-reopen from the gate queue once this issue is labeled
accepted.Quick summary of the approach so you can veto cheaply before reviewing:
Memory._add_to_vector_store/AsyncMemory._add_to_vector_storenow track which records actually persisted (batch insert success = all persisted; on fallback, only records whose per-record insert succeeded).ADDhistory row, and are not referenced by entitylinked_memory_ids.add()raisesVectorStoreError— which the docstring already documented but nothing raised. Raw messages are still saved first so a retry can re-extract.One semantic choice worth confirming: on partial failure the call still succeeds and returns only the persisted records (rather than raising). If you would prefer partial failures to also raise, or to surface per-record status in the payload, I can adjust #7066 in a minute.
4 regression tests included; full
tests/memory/suite (377 tests) and ruff are green.