shareAI-lab/learn-claude-code · warning · ValueError
The memory index is not a memory record
Error message
The memory index is not a memory record
What it means
Raised by memory_path() in s09_memory/code.py when the caller passes the memory index file's name (MEMORY_INDEX.name, e.g. INDEX.md) without allow_index=True. The index is a generated catalog of memory records, not a record itself, so record-oriented tools (read/write/delete a memory) refuse to operate on it to prevent corruption or recursive self-reference. Only the dedicated index-rebuild path passes allow_index=True.
Source
Thrown at s09_memory/code.py:92
if len(parts) < 3:
return {}, text
try:
metadata = yaml.safe_load(parts[1]) or {}
except yaml.YAMLError:
return {}, text
if not isinstance(metadata, dict):
return {}, text
return metadata, parts[2].lstrip()
def memory_slug(name: str) -> str:
slug = re.sub(r"[^\w]+", "-", name.lower()).strip("-_")
return slug or "memory"
def memory_path(filename: str, allow_index: bool = False) -> Path:
if Path(filename).name != filename:
raise ValueError(f"Invalid memory filename: {filename}")
if filename == MEMORY_INDEX.name and not allow_index:
raise ValueError("The memory index is not a memory record")
root = MEMORY_DIR.resolve()
if not root.is_relative_to(WORKDIR.resolve()):
raise ValueError("Memory directory escapes the workspace")
path = (root / filename).resolve()
if not path.is_relative_to(root):
raise ValueError(f"Memory path escapes the store: {filename}")
return path
def _memory_slug(name: str) -> str:
return memory_slug(name)
def _normalized_memory_text(value: str) -> str:
return " ".join(value.lower().split())
def should_store_memory(candidate: dict, existing: list[dict]) -> bool:
"""Accept durable records that are not temporary or already stored."""
if not isinstance(candidate, dict):View on GitHub (pinned to 985456f4ad)
Solutions
- Filter the index filename out of any directory listing before per-record calls
- Choose memory names that do not slug down to the index filename
- Only the index-maintenance code path should pass allow_index=True; never expose that flag through the agent tool surface
Example fix
// before
for f in MEMORY_DIR.iterdir():
memory_read(f.name) # blows up on INDEX file
// after
for f in MEMORY_DIR.iterdir():
if f.name != MEMORY_INDEX.name:
memory_read(f.name) Defensive patterns
Strategy: validation
Validate before calling
INDEX_NAME = MEMORY_INDEX.name # e.g. 'INDEX.md'
records = [f for f in MEMORY_DIR.iterdir() if f.name != INDEX_NAME]
for f in records:
memory_read(f.name) Type guard
def is_memory_record(filename: str) -> bool:
return filename != MEMORY_INDEX.name and Path(filename).name == filename Try / catch
try:
memory_path(fn)
except ValueError as e:
if 'index is not a memory record' in str(e):
skip = True # it's the catalog, not a record
else:
raise Prevention
- Always filter the index file out of directory scans before per-record operations
- Never expose allow_index=True through the agent tool surface
- Avoid memory names whose slug collides with the index filename
When it happens
Trigger: A memory tool call with filename equal to the index file's name; listing or globbing MEMORY_DIR and feeding every resulting filename back into a per-record tool without filtering out the index; a memory slug that happens to collide with the index filename.
Common situations: Agent iterating directory contents and treating every file as a record; user-visible index file tempting direct edits; slug collisions when memory names sanitize to 'index'.
Related errors
- Memory name cannot be empty
- Unknown memory type: {mem_type}
- Memory description and body cannot be empty
- Max 20 todos allowed
- Item {item_id}: text required
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/e065285251c49251.
Report an issue: GitHub.