🐛 Describe the bug
Bug Report: actor_id metadata gets overwritten during memory UPDATE operations
Description
I believe I may have found a bug related to actor_id handling in multi-actor scenarios. When using metadata={"actor_id": ...} with shared user_id, the actor_id field appears to be overwritten when a different actor triggers an UPDATE event, which seems to break actor-level memory isolation and query filtering.
I'm not sure if this is the intended behavior, but I wanted to report it in case it's helpful.
Steps to Reproduce
from mem0 import Memory
m = Memory.from_config(config)
# Step 1: Actor A creates memory
result_a = m.add(
[{"role": "user", "content": "I am player #1"}],
user_id="team",
metadata={"actor_id": "Alice"}
)
# ✓ Memory created with actor_id="Alice"
# Step 2: Actor B updates A's memory
result_b = m.add(
[{"role": "user", "content": "Player #1 is a good person"}],
user_id="team",
metadata={"actor_id": "Bob"}
)
# ❌ Memory updated but actor_id becomes "Bob"
# Step 3: Query by original creator
alice_memories = m.search(query="", user_id="team", filters={"actor_id": "Alice"})
print(f"Query Alice's memories: {len(alice_memories['results'])} found")
# Returns: 0 found
Expected Behavior
After Bob's UPDATE:
- Memory content should be updated:
"Player #1 is a good person"
actor_id should remain: "Alice" (original creator)
- Query
filters={"actor_id": "Alice"} should return 1 result
Actual Behavior
After Bob's UPDATE:
- Memory content is updated correctly ✓
actor_id is overwritten to: "Bob" ❌
- Query
filters={"actor_id": "Alice"} returns empty ❌
Output:
=== State AFTER Bob's UPDATE ===
Event: UPDATE
This actor_id: 'Bob' ← Overwritten!
ISOLATION TEST:
Query Alice's memories: 0 found
❌ BUG: Alice's memory lost!
Impact
- Cannot query by original creator after UPDATE
- Memory ownership tracking lost - can't identify who created the memory
- Actor isolation fails in shared
user_id scenarios (e.g., team workspaces, multi-player games, collaborative agents)
Root Cause
In mem0/memory/main.py, the _update_memory() method (lines 1251-1252 for sync, 2347-2349 for async):
# Current implementation
if "actor_id" not in new_metadata and "actor_id" in existing_memory.payload:
new_metadata["actor_id"] = existing_memory.payload["actor_id"]
Issue: The condition checks "actor_id" not in new_metadata, but new_metadata always contains the current actor's ID (passed from line 1668/1662 via metadata=deepcopy(metadata)), so preservation never happens.
Possible Solution (If This Is Indeed a Bug)
I've done some investigation and found that the issue might be in the condition check at lines 1251-1252 (sync) and 2347-2349 (async). Perhaps removing the condition check could help preserve the original actor_id:
# Suggested modification
if "actor_id" in existing_memory.payload:
new_metadata["actor_id"] = existing_memory.payload["actor_id"]
This would treat actor_id as "memory owner" rather than "last updater". The history table (db.add_history()) already tracks all contributors, so update history wouldn't be lost.
However, I'm not familiar with the full design intentions, so this is just my humble suggestion. Please feel free to correct me if I'm misunderstanding something!
My Testing (For Reference)
I've tried to verify this potential fix using a monkey patch on my local setup:
Monkey Patch Test (Click to expand)
from mem0.memory.main import Memory as MemoryClass
def _patched_update_memory(self, memory_id, data, existing_embeddings, metadata=None):
# ... (identical to original except:)
# ===== FIX =====
if "actor_id" in existing_memory.payload:
new_metadata["actor_id"] = existing_memory.payload["actor_id"]
# ===============
# ... (rest unchanged)
MemoryClass._update_memory = _patched_update_memory
# Run same test...
Output (After Fix):
=== State AFTER Bob's UPDATE ===
Event: UPDATE
This actor_id: 'Alice' ← Preserved!
ISOLATION TEST:
Query Alice's memories: 1 found
✅ SUCCESS: Alice's memory preserved!
Environment
- Mem0 version: v1.0.7
- Python: 3.13
- Vector Store: Qdrant (local)
- OS: macOS
Additional Context
- This affects both sync and async implementations of
_update_memory()
- The same issue applies to any custom metadata fields that should be preserved across updates
- Current behavior is inconsistent with how
user_id, agent_id, and run_id are preserved (lines 1245-1250)
Use Cases Affected
- Multi-player games: Shared team memory with per-player contributions
- Collaborative AI agents: Multiple agents updating shared knowledge base
- Team workspaces: Tracking which team member created each memory
- Multi-user chatbots: Preserving memory ownership in shared conversations
Request for Feedback
I would really appreciate it if the maintainers could take a look at this issue and let me know if:
- This is indeed a bug or if it's the intended behavior
- My understanding of the root cause is correct
- The suggested fix makes sense for the overall design
If this is confirmed as a bug and the proposed solution is acceptable, I would be honored to submit a Pull Request with the fix (including proper tests if needed). I've already prepared a draft PR and tested it locally with the monkey patch approach.
Of course, if there's a better way to handle this or if I'm missing something important, please feel free to guide me. I'm still learning about the codebase and would love any feedback!
Thank you so much for creating and maintaining this excellent library. It's been incredibly useful for my project! 🙏
🐛 Describe the bug
Bug Report:
actor_idmetadata gets overwritten during memory UPDATE operationsDescription
I believe I may have found a bug related to
actor_idhandling in multi-actor scenarios. When usingmetadata={"actor_id": ...}with shareduser_id, theactor_idfield appears to be overwritten when a different actor triggers an UPDATE event, which seems to break actor-level memory isolation and query filtering.I'm not sure if this is the intended behavior, but I wanted to report it in case it's helpful.
Steps to Reproduce
Expected Behavior
After Bob's UPDATE:
"Player #1 is a good person"actor_idshould remain:"Alice"(original creator)filters={"actor_id": "Alice"}should return 1 resultActual Behavior
After Bob's UPDATE:
actor_idis overwritten to:"Bob"❌filters={"actor_id": "Alice"}returns empty ❌Output:
Impact
user_idscenarios (e.g., team workspaces, multi-player games, collaborative agents)Root Cause
In
mem0/memory/main.py, the_update_memory()method (lines 1251-1252 for sync, 2347-2349 for async):Issue: The condition checks
"actor_id" not in new_metadata, butnew_metadataalways contains the current actor's ID (passed from line 1668/1662 viametadata=deepcopy(metadata)), so preservation never happens.Possible Solution (If This Is Indeed a Bug)
I've done some investigation and found that the issue might be in the condition check at lines 1251-1252 (sync) and 2347-2349 (async). Perhaps removing the condition check could help preserve the original
actor_id:This would treat
actor_idas "memory owner" rather than "last updater". The history table (db.add_history()) already tracks all contributors, so update history wouldn't be lost.However, I'm not familiar with the full design intentions, so this is just my humble suggestion. Please feel free to correct me if I'm misunderstanding something!
My Testing (For Reference)
I've tried to verify this potential fix using a monkey patch on my local setup:
Monkey Patch Test (Click to expand)
Output (After Fix):
Environment
Additional Context
_update_memory()user_id,agent_id, andrun_idare preserved (lines 1245-1250)Use Cases Affected
Request for Feedback
I would really appreciate it if the maintainers could take a look at this issue and let me know if:
If this is confirmed as a bug and the proposed solution is acceptable, I would be honored to submit a Pull Request with the fix (including proper tests if needed). I've already prepared a draft PR and tested it locally with the monkey patch approach.
Of course, if there's a better way to handle this or if I'm missing something important, please feel free to guide me. I'm still learning about the codebase and would love any feedback!
Thank you so much for creating and maintaining this excellent library. It's been incredibly useful for my project! 🙏