headroomlabs-ai/headroom · error · ValueError
Memory {new_memory_id} not found
Error message
Memory {new_memory_id} not found What it means
Raised by detach_supersession when the new memory ID is not found in the memories table. Both edge endpoints must exist for the reciprocal edge check and the subsequent UPDATEs; a missing new endpoint aborts the transaction before any writes.
Source
Thrown at headroom/memory/adapters/sqlite.py:733
untouched.
"""
if old_memory_id == new_memory_id:
raise ValueError("A memory cannot supersede itself")
with self._get_conn() as conn:
conn.execute("BEGIN IMMEDIATE")
rows = conn.execute(
"SELECT * FROM memories WHERE id IN (?, ?)",
(old_memory_id, new_memory_id),
).fetchall()
memories = {row["id"]: self._row_to_memory(row) for row in rows}
old_memory = memories.get(old_memory_id)
new_memory = memories.get(new_memory_id)
if old_memory is None:
raise ValueError(f"Memory {old_memory_id} not found")
if new_memory is None:
raise ValueError(f"Memory {new_memory_id} not found")
if old_memory.superseded_by != new_memory_id or new_memory.supersedes != old_memory_id:
raise ValueError(
f"Memories {old_memory_id} and {new_memory_id} do not form "
"a reciprocal supersession edge"
)
conn.execute(
"UPDATE memories SET valid_until = NULL, superseded_by = NULL WHERE id = ?",
(old_memory_id,),
)
conn.execute(
"UPDATE memories SET supersedes = NULL WHERE id = ?",
(new_memory_id,),
)
old_memory.valid_until = None
old_memory.superseded_by = None
new_memory.supersedes = NoneView on GitHub (pinned to 322425c43b)
Solutions
- Confirm both memories exist before detaching; query by both IDs in one call.
- If the new memory is intentionally gone, clear the dangling superseded_by/supersedes columns directly as a data repair.
- Restore the missing row from backup if chain integrity matters.
Example fix
// before
await store.detach_supersession(old_id, new_id)
// after
rows = await store.get_many([old_id, new_id])
if rows.get(old_id) and rows.get(new_id):
await store.detach_supersession(old_id, new_id)
else:
logger.warning("endpoint missing; skipping detach") Defensive patterns
Strategy: try-catch
Validate before calling
if await store.get(new_memory_id) is None:
logger.warning("new endpoint missing; clearing dangling edge manually")
return Try / catch
try:
old_m, new_m = await store.detach_supersession(old_id, new_id)
except ValueError as e:
logger.warning("detach failed, likely dangling edge: %s", e) Prevention
- Never hard-delete one endpoint of a supersession pair; detach first, then delete.
- Run integrity checks for dangling superseded_by/supersedes pointers after migrations.
When it happens
Trigger: The new memory was hard-deleted but the old one still points at it (dangling superseded_by); passing the new memory before it was saved; ID typos in manual repair invocations.
Common situations: Partial deletes that broke chain integrity; repair tooling operating on half-migrated data; concurrent writes deleting one endpoint.
Related errors
- Memory with ID {old_memory_id} not found
- Memory {old_memory_id} not found
- 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
- A memory cannot supersede itself
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/82ff8d4693ef05f8.
Report an issue: GitHub.