Description
Empty SESSION SUMMARY records appear in the UI with no title, no body — just the session number and timestamp. The summary card renders but contains no meaningful content.
Root Cause Analysis
After investigating the logs and SQLite data, the root cause was identified:
The parser design issue
The response handler function calls both parseObservations and parseSummary on every LLM response, regardless of whether the response was a summarize request or an observation request.
parseSummary uses the regex /<summary>([\s\S]*?)<\/summary>/ to match. When an observation response accidentally contains text that matches the <summary>...</summary> pattern, the parser creates a summary record.
However, since the matched content doesn't contain the expected sub-tags (<request>, <investigated>, <learned>, <completed>, <next_steps>), all fields are parsed as null, then converted to empty strings — resulting in a completely empty summary record being saved to SQLite.
Step-by-step reproduction path
- An observation is generated from a normal tool use (e.g., PostToolUse hook)
- The LLM returns a response wrapped in
<observation> tags
- The response handler calls
parseObservations (works correctly) and parseSummary
parseSummary regex accidentally matches a <summary>...</summary> pattern within the observation response
- Sub-tag parsing returns
null for all fields → converted to ""
- Empty summary record is saved to SQLite with
documentCount=0
- ChromaDB sync completes in 1ms (nothing to sync)
- UI renders an empty SESSION SUMMARY card
Evidence
- SQLite record: all fields (
request, investigated, learned, completed, next_steps, notes) are empty strings
- ChromaDB sync:
documentCount=0 (nothing synced)
- Log shows the response started with
<observation> tag, not a summarize response
- This has occurred at least 3 times across different dates (confirmed via SQLite query)
Suggested Fixes
- Guard parseSummary calls — Only call
parseSummary when the request was actually a summarize prompt (e.g., check promptNumber or request type)
- Validate before saving — Reject summary records where all fields are empty
- UI-side filter — Don't render SESSION SUMMARY cards when all content fields are empty
Option 1 is the root cause fix. Options 2 and 3 are defense-in-depth.
Environment
- claude-mem: latest (installed via plugin marketplace)
- Claude Code: v2.1.76
- OS: WSL2 (Ubuntu) on Windows
- Model: Opus 4.6 [1M context]
Related Issues
Description
Empty SESSION SUMMARY records appear in the UI with no title, no body — just the session number and timestamp. The summary card renders but contains no meaningful content.
Root Cause Analysis
After investigating the logs and SQLite data, the root cause was identified:
The parser design issue
The response handler function calls both
parseObservationsandparseSummaryon every LLM response, regardless of whether the response was a summarize request or an observation request.parseSummaryuses the regex/<summary>([\s\S]*?)<\/summary>/to match. When an observation response accidentally contains text that matches the<summary>...</summary>pattern, the parser creates a summary record.However, since the matched content doesn't contain the expected sub-tags (
<request>,<investigated>,<learned>,<completed>,<next_steps>), all fields are parsed asnull, then converted to empty strings — resulting in a completely empty summary record being saved to SQLite.Step-by-step reproduction path
<observation>tagsparseObservations(works correctly) andparseSummaryparseSummaryregex accidentally matches a<summary>...</summary>pattern within the observation responsenullfor all fields → converted to""documentCount=0Evidence
request,investigated,learned,completed,next_steps,notes) are empty stringsdocumentCount=0(nothing synced)<observation>tag, not a summarize responseSuggested Fixes
parseSummarywhen the request was actually a summarize prompt (e.g., checkpromptNumberor request type)Option 1 is the root cause fix. Options 2 and 3 are defense-in-depth.
Environment
Related Issues
<observation>instead of<summary>(different root cause)