headroomlabs-ai/headroom · error · ValueError
Memory {old_memory_id} not found
Error message
Memory {old_memory_id} not found What it means
ValueError raised by MemorySystem.supersede() when the backing store's get(old_memory_id) returns None. Superseding marks a memory as replaced by creating a new memory that inherits its scope and invalidating the old one, so the old memory must exist first.
Source
Thrown at headroom/memory/core.py:563
auto_embed: Whether to embed the new content.
Returns:
The new Memory that supersedes the old one.
Raises:
ValueError: If old memory not found.
Example:
# User's preference changed
new_mem = await system.supersede(
old_memory.id,
"User now prefers JavaScript over Python",
)
"""
# Get old memory
old_memory = await self._store.get(old_memory_id)
if old_memory is None:
raise ValueError(f"Memory {old_memory_id} not found")
# Create new memory with same scope
new_memory = Memory(
content=new_content,
user_id=old_memory.user_id,
session_id=old_memory.session_id,
agent_id=old_memory.agent_id,
turn_id=old_memory.turn_id,
importance=old_memory.importance,
entity_refs=old_memory.entity_refs.copy(),
metadata=old_memory.metadata.copy(),
)
# Embed new content
if auto_embed:
new_memory.embedding = await self._embedder.embed(new_content)
# Perform supersession in storeView on GitHub (pinned to 322425c43b)
Solutions
- Verify the old memory exists (await system.get(old_memory_id)) and skip/save-fresh if it is gone
- Make supersede flows idempotent: treat 'not found' as 'nothing to supersede' and just create the new memory
- Re-fetch ids at the moment of supersede instead of caching them across sessions
Example fix
# before
new_mem = await system.supersede(old_id, 'User now prefers JS')
# ValueError: Memory {old_id} not found
# after
old = await system.get(old_id)
if old is None:
new_mem = await system.save('User now prefers JS', user_id=user_id)
else:
new_mem = await system.supersede(old_id, 'User now prefers JS') Defensive patterns
Strategy: validation
Validate before calling
old = await system.get(old_memory_id)
if old is None:
# nothing to supersede; create fresh instead
new_mem = await system.save(new_content, user_id=user_id)
else:
new_mem = await system.supersede(old_memory_id, new_content) Try / catch
try:
new_mem = await system.supersede(old_memory_id, new_content)
except ValueError as e:
if 'not found' in str(e):
new_mem = await system.save(new_content, user_id=user_id)
else:
raise Prevention
- Design supersede flows idempotently: missing old memory degrades to a plain save
- Fetch ids fresh instead of caching across sessions/resets
- Guard against double-processing events that supersede the same memory twice
When it happens
Trigger: await system.supersede(old_memory_id, 'new content') where old_memory_id was already deleted, superseded, or never existed; also after a store reset while the app still holds old ids.
Common situations: Preference-change flows where the old memory expired or was garbage-collected; double-processing the same event superseding twice; ids from a previous environment (dev id used against prod store).
Related errors
- max_size must be at least 1, got {max_size}
- Memory not found: {memory_id}
- bedrock_eventstream_parse_failed
- items_json must be JSON: {e}
- doc_json must be JSON: {e}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/2b143e76bc8e4cc6.
Report an issue: GitHub.