headroomlabs-ai/headroom · error · ValueError
Ambiguous ID '{memory_id}'. Matches: {[memory.id[:8] for mem
Error message
Ambiguous ID '{memory_id}'. Matches: {[memory.id[:8] for memory in matches]} What it means
When _resolve_memory's exact lookup misses but multiple stored memory IDs share the given prefix, it refuses to guess and raises ValueError listing the first 8 chars of every match. This is a deliberate unambiguity guarantee: prefix shortcuts must resolve to exactly one memory or the command aborts before mutating anything.
Source
Thrown at headroom/cli/memory.py:224
except Exception as exc:
print_warning(f"Vector index cleanup incomplete: {exc}")
ok = False
return ok
def _resolve_memory(store: SQLiteMemoryStore, memory_id: str) -> Memory:
"""Resolve an exact or unambiguous partial memory ID."""
memory = asyncio.run(store.get(memory_id))
if memory is not None:
return memory
memories = asyncio.run(store.query(MemoryFilter(limit=10000, include_superseded=True)))
matches = [candidate for candidate in memories if candidate.id.startswith(memory_id)]
if not matches:
raise ValueError(f"Memory not found: {memory_id}")
if len(matches) > 1:
raise ValueError(
f"Ambiguous ID '{memory_id}'. Matches: {[memory.id[:8] for memory in matches]}"
)
return matches[0]
async def _apply_supersession_repair(
db_path: str,
old_memory_id: str,
new_memory_id: str,
vector_dimension: int,
) -> tuple[Memory, Memory]:
"""Apply a repair through LocalBackend so indexes and cache are refreshed."""
from ..memory.backends.local import LocalBackend, LocalBackendConfig
backend = LocalBackend(
LocalBackendConfig(
db_path=db_path,
vector_dimension=vector_dimension,View on GitHub (pinned to 322425c43b)
Solutions
- Extend the prefix until it matches exactly one ID listed in the error's Matches array
- Copy the full ID from `headroom memory list` output
- In scripts, never truncate IDs below the length that keeps them unique — store full IDs
- Prune/supersede old memories if ID collisions come from duplicate near-identical entries
Example fix
# before $ headroom memory show 3f # Ambiguous ID '3f'. Matches: ['3f9c1d2e', '3f77aa01'] # after $ headroom memory show 3f9c1d2e4a5b6c7d
Defensive patterns
Strategy: validation
Validate before calling
import asyncio
from headroom.memory import MemoryFilter
def unique_prefix_ok(store, prefix: str) -> tuple[bool, int]:
if asyncio.run(store.get(prefix)) is not None:
return True, 1
hits = [m for m in asyncio.run(store.query(MemoryFilter(limit=10000, include_superseded=True)))
if m.id.startswith(prefix)]
return len(hits) == 1, len(hits) Try / catch
try:
mem = _resolve_memory(store, memory_id)
except ValueError as e:
if str(e).startswith("Ambiguous ID"):
# message lists candidate 8-char prefixes — extend and retry
candidates = parse_matches(str(e))
raise SystemExit(f"extend prefix; candidates: {candidates}")
raise Prevention
- Store full memory IDs in automation; never truncate below ~12 chars
- Parse the Matches list from the error to auto-extend the prefix
- Reduce superseded duplicates so prefix collisions are rare
When it happens
Trigger: Passing a short prefix (e.g. 2-4 hex chars) that is a prefix of several memory IDs, e.g. `headroom memory show 3f` when 3f9c1d2e... and 3f77aa01... both exist (superseded memories included).
Common situations: Users abbreviating long UUIDs too aggressively; DBs with many memories where random short prefixes collide; scripts truncating IDs to a fixed short width.
Related errors
- Memory not found: {memory_id}
- Memories {old_memory.id} and {new_memory.id} do not form a r
- max_size must be at least 1, got {max_size}
- Memory {old_memory_id} not found
- bedrock_eventstream_parse_failed
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/a2e4f1a4cf8a643e.
Report an issue: GitHub.