headroomlabs-ai/headroom · error · ValueError
Memory with ID {old_memory_id} not found
Error message
Memory with ID {old_memory_id} not found What it means
Raised by the SQLite memory store's supersede operation when the old memory ID does not exist. Supersession must link an existing old memory to a new one, so a missing old record (checked via get) aborts before any lineage fields are written.
Source
Thrown at headroom/memory/adapters/sqlite.py:658
Args:
old_memory_id: ID of the memory to supersede.
new_memory: The new memory that replaces it.
supersede_time: When the supersession occurred (defaults to now).
Returns:
The saved new memory with lineage fields populated.
Raises:
ValueError: If the old memory is not found.
"""
if supersede_time is None:
supersede_time = datetime.now(timezone.utc).replace(tzinfo=None)
# Get the old memory
old_memory = await self.get(old_memory_id)
if old_memory is None:
raise ValueError(f"Memory with ID {old_memory_id} not found")
# Update old memory's valid_until and superseded_by
old_memory.valid_until = supersede_time
old_memory.superseded_by = new_memory.id
# Set up new memory's lineage
new_memory.supersedes = old_memory_id
new_memory.valid_from = supersede_time
# Save both in a transaction
with self._get_conn() as conn:
# Update old memory
conn.execute(
"""
UPDATE memories
SET valid_until = ?, superseded_by = ?
WHERE id = ?
""",View on GitHub (pinned to 322425c43b)
Solutions
- Fetch the old memory first and verify it exists before building the superseding memory.
- Check for concurrent deletion (TTL jobs, compaction) and re-read IDs at operation time.
- Handle the ValueError as a signal the chain is already gone and skip/log the supersession.
Example fix
// before
await store.supersede(old_id, new_memory)
// after
if await store.get(old_id) is None:
logger.warning("cannot supersede missing %s", old_id)
else:
await store.supersede(old_id, new_memory) Defensive patterns
Strategy: validation
Validate before calling
if await store.get(old_memory_id) is None:
raise KeyError(f"memory {old_memory_id} vanished; cannot supersede") Try / catch
try:
saved = await store.supersede(old_id, new_memory)
except ValueError as e:
logger.warning("supersede skipped: %s", e) Prevention
- Re-read IDs at operation time instead of caching them across sessions.
- Watch for TTL/cleanup jobs that can delete the old memory concurrently.
When it happens
Trigger: Calling supersede(old_id, new_memory) after the old memory was deleted; passing an ID with a typo or wrong format; concurrent deletion between the caller's read and the supersede call.
Common situations: Stale IDs held from earlier sessions; race with a cleanup/TTL job that deleted the old memory; IDs from a different environment/database.
Related errors
- Memory {old_memory_id} not found
- Memory {new_memory_id} not found
- A memory cannot supersede itself
- Memories {old_memory_id} and {new_memory_id} do not form a r
- Memories {old_memory.id} and {new_memory.id} do not form a r
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/62978e5b4483fb43.
Report an issue: GitHub.