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 store

View on GitHub (pinned to 322425c43b)

Solutions

  1. Verify the old memory exists (await system.get(old_memory_id)) and skip/save-fresh if it is gone
  2. Make supersede flows idempotent: treat 'not found' as 'nothing to supersede' and just create the new memory
  3. 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

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


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