headroomlabs-ai/headroom · error · ValueError

A memory cannot supersede itself

Error message

A memory cannot supersede itself

What it means

Raised by detach_supersession when old_memory_id equals new_memory_id. A self-edge would mean a memory supersedes itself, which is logically invalid, and detaching it is a no-op at best and graph corruption at worst, so it is rejected up front.

Source

Thrown at headroom/memory/adapters/sqlite.py:718

                row,
            )
            conn.commit()

        return new_memory

    async def detach_supersession(
        self,
        old_memory_id: str,
        new_memory_id: str,
    ) -> tuple[Memory, Memory]:
        """Atomically detach one verified supersession edge.

        This is an explicit repair operation. It never infers identity from
        content or embedding similarity and leaves neighboring chain edges
        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 "

View on GitHub (pinned to 322425c43b)

Solutions

  1. Skip pairs where old == new before calling detach_supersession.
  2. Fix the upstream variable assignment that produces identical IDs.
  3. Treat this error as a symptom of a corrupted edge list and audit how the pairs were generated.

Example fix

// before
await store.detach_supersession(mem.id, mem.id)

// after
if old_id != new_id:
    await store.detach_supersession(old_id, new_id)
Defensive patterns

Strategy: validation

Validate before calling

if old_memory_id == new_memory_id:
    raise ValueError("self-supersession attempted")
await store.detach_supersession(old_memory_id, new_memory_id)

Prevention

When it happens

Trigger: Both parameters filled from the same variable (e.g. superseded_by and supersedes accidentally swapped or duplicated); programmatic edge lists generated with a copy-paste bug producing (id, id) pairs.

Common situations: Loop constructing edge pairs where old and new collapse to the same value; defensive repair scripts iterating IDs that accidentally pair a memory with itself.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/ae7058d7458def41. Report an issue: GitHub.