headroomlabs-ai/headroom · error · ValueError

Memories {old_memory.id} and {new_memory.id} do not form a r

Error message

Memories {old_memory.id} and {new_memory.id} do not form a reciprocal supersession edge

What it means

repair-supersession is a narrow maintenance command: it only detaches a broken pair where old.superseded_by == new.id AND new.supersedes == old.id (a reciprocal edge). If either side of the edge is missing or points elsewhere (half-written supersession, IDs swapped, or one side repaired already), the reciprocity check fails with this ValueError before any repair is applied.

Source

Thrown at headroom/cli/memory.py:841

    """Detach one incorrect OLD_ID -> NEW_ID supersession edge.

    The command validates both reciprocal lineage pointers and changes no
    neighboring edges. It is a dry run unless ``--apply`` is provided.

    \b
    Examples:
        headroom memory repair-supersession OLD_ID NEW_ID
        headroom memory repair-supersession OLD_ID NEW_ID --apply
    """
    _ = ctx
    store = get_store(db_path)

    try:
        old_memory = _resolve_memory(store, old_memory_id)
        new_memory = _resolve_memory(store, new_memory_id)

        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"
            )

        click.echo("\nSupersession repair preview:")
        click.echo(
            f"  Restore old memory: {old_memory.id} "
            f"({truncate(old_memory.content.replace(chr(10), ' '), 60)})"
        )
        click.echo(
            f"  Detach new memory: {new_memory.id} "
            f"({truncate(new_memory.content.replace(chr(10), ' '), 60)})"
        )
        click.echo("  Clear: old.valid_until, old.superseded_by, new.supersedes")

        if not apply_change:
            print_warning("DRY RUN: No changes made. Re-run with --apply to repair this edge.")
            return

View on GitHub (pinned to 322425c43b)

Solutions

  1. Swap the argument order and retry — OLD must be the memory whose superseded_by points at NEW
  2. Inspect both memories first (`headroom memory show <id>`) and confirm old.superseded_by == new.id and new.supersedes == old.id
  3. If one side is already detached, no repair is needed — re-check the store state
  4. For other corruption shapes, use the lower-level store API or open an issue rather than forcing this command

Example fix

# before
$ headroom memory repair-supersession NEW_ID OLD_ID
# ValueError: Memories ... do not form a reciprocal supersession edge

# after
$ headroom memory repair-supersession OLD_ID NEW_ID
Defensive patterns

Strategy: validation

Validate before calling

old = asyncio.run(store.get(old_id)) or prefix_match(old_id)
new = asyncio.run(store.get(new_id)) or prefix_match(new_id)
if old.superseded_by != new.id or new.supersedes != old.id:
    raise SystemExit(
        "edge not reciprocal — check argument order (OLD NEW) "
        f"old.superseded_by={old.superseded_by} new.supersedes={new.supersedes}"
    )

Try / catch

try:
    run_repair(old_id, new_id)
except ValueError as e:
    if "reciprocal supersession edge" in str(e):
        print("preconditions not met — nothing changed; inspect both memories and arg order")
        sys.exit(2)
    raise

Prevention

When it happens

Trigger: Running `headroom memory repair-supersession OLD NEW` where the two memories do not mutually reference each other — e.g. passing OLD/NEW in the wrong order, one of them was already detached by a previous repair, or the corruption is a different shape (one-sided superseded_by with no matching supersedes).

Common situations: Arguments swapped (NEW OLD instead of OLD NEW); re-running a repair that already succeeded; diagnosing an inconsistent store whose edges were partially written; copy-pasting IDs from different pairs.

Related errors


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