{"record":{"id":"f563316ed68c9931","repo":"shareAI-lab/learn-claude-code","slug":"memory-name-cannot-be-empty","errorCode":null,"errorMessage":"Memory name cannot be empty","messagePattern":"Memory name cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s09_memory/code.py","lineNumber":151,"sourceCode":"        if _normalized_memory_text(\n            str(memory.get(\"description\", \"\"))\n        ) == normalized_description:\n            return False\n        if _normalized_memory_text(str(memory.get(\"body\", \"\"))) == normalized_body:\n            return False\n    return True\n\ndef memory_document(name: str, mem_type: str, description: str, body: str) -> str:\n    metadata = yaml.safe_dump(\n        {\"name\": name, \"description\": description, \"type\": mem_type},\n        sort_keys=False,\n        allow_unicode=True,\n    ).strip()\n    return f\"---\\n{metadata}\\n---\\n\\n{body.strip()}\\n\"\n\ndef write_memory_file(name: str, mem_type: str, description: str, body: str) -> Path:\n    if not name.strip():\n        raise ValueError(\"Memory name cannot be empty\")\n    if mem_type not in MEMORY_TYPES:\n        raise ValueError(f\"Unknown memory type: {mem_type}\")\n    if not description.strip() or not body.strip():\n        raise ValueError(\"Memory description and body cannot be empty\")\n\n    MEMORY_DIR.mkdir(parents=True, exist_ok=True)\n    path = memory_path(f\"{memory_slug(name)}.md\")\n    path.write_text(memory_document(name, mem_type, description, body))\n    rebuild_memory_index()\n    return path\n\ndef rebuild_memory_index() -> None:\n    MEMORY_DIR.mkdir(parents=True, exist_ok=True)\n    lines = []\n    for path in sorted(MEMORY_DIR.glob(\"*.md\")):\n        if path.name == MEMORY_INDEX.name:\n            continue\n        try:","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s09_memory/code.py#L133-L169","documentation":"Raised by write_memory_file() in s09_memory/code.py:151 when the memory record's name is empty after stripping whitespace. Every durable memory record must have a non-empty name because the name is slugified (memory_slug(name)) to produce the record's filename; an empty name would yield an empty or invalid filename. The check runs before any type or content validation and before the store directory is touched.","triggerScenarios":"Calling write_memory_file('', 'user', 'desc', 'body'), passing a name composed only of whitespace like '   ', or passing a programmatically derived name (e.g. a field extracted from LLM output) that is None/empty after strip. Note None fails too: name.strip() raises AttributeError, so empty strings and whitespace-only strings are the exact triggers.","commonSituations":"Consolidation or capture pipelines that build the name from optional fields (record.get('name', '')) without a presence check; UI forms submitted empty; LLM-generated record dicts where the name key was omitted or blank.","solutions":["Check that the name is a non-empty string after strip() before calling write_memory_file().","If the name comes from LLM output, validate with validate_memory_record() first — it rejects empty names — or derive a fallback name from the description's first words.","Fix the upstream producer so it never emits an empty name field."],"exampleFix":"# before\nwrite_memory_file(record.get('name', ''), mem_type, description, body)\n\n# after\nname = (record.get('name') or '').strip()\nif not name:\n    raise ValueError('record missing a name')\nwrite_memory_file(name, mem_type, description, body)","handlingStrategy":"validation","validationCode":"def has_memory_name(name) -> bool:\n    return isinstance(name, str) and bool(name.strip())","typeGuard":"def is_valid_memory_name(name) -> bool:\n    return isinstance(name, str) and len(name.strip()) > 0","tryCatchPattern":"try:\n    write_memory_file(name, mem_type, description, body)\nexcept ValueError as e:\n    if 'cannot be empty' in str(e):\n        # fill a default or surface to caller\n        name = fallback_name or 'unnamed-record'","preventionTips":["Validate all record fields (name/type/description/body) before writing.","Prefer validate_memory_record() on any LLM-produced dict before persisting.","Treat empty names as a producer bug: log and skip rather than defaulting silently."],"tags":["validation","memory","user-input"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}