thedotmack/claude-mem · warning
Failed to parse files_read JSON
Error message
Failed to parse files_read JSON
What it means
The second parse attempt in extractRelevantFile: obs.files_read is parsed as a JSON array of paths to find a direct child of the folder. Invalid JSON triggers this warning and the function returns 'General' as the section label. Non-fatal; only the generated CLAUDE.md section naming degrades.
Solutions
- Rewrite files_read as a valid JSON array of path strings
- Null the field when empty rather than storing '' or garbage
- Regenerate the observation via the normal capture pipeline
- Add a migration to normalize/blank legacy malformed values
Example fix
// before obs.files_read = '["src/a.ts"'; // after obs.files_read = '["src/a.ts"]';
Defensive patterns
Strategy: validation
Validate before calling
if (obs.files_read) {
try { const read = JSON.parse(obs.files_read); if (Array.isArray(read)) { /* use */ } } catch { /* use 'General' */ }
} Type guard
function isJsonArrayString(v: unknown): v is string { return typeof v === 'string' && v.trimStart().startsWith('['); } Try / catch
try { read = JSON.parse(obs.files_read); } catch { read = []; } // default keeps flow to 'General' Prevention
- Never hand-edit observation JSON in the DB
- Regenerate observations via the pipeline instead of patching rows
- Guard writers so partial/truncated writes cannot persist
- Add integration tests covering empty and legacy field values
When it happens
Trigger: obs.files_read holds malformed JSON — a plain path string, truncated array like '["src/a.ts"', single-quoted entries, or non-string JSON (e.g. an object) that passes parse but not Array.isArray, leaving paths undefined downstream (though the warn itself fires only on throw).
Common situations: Historic rows predating the array format; corrupted DB rows after a crash; observations written by external scripts; manual DB edits.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse files_modified JSON
- Expected JSON array in observation list field, using plain…
- Failed to parse files JSON in hasDirectChildFile
- [SETTINGS] Failed to load settings, using defaults:
- sync hub status: response is not JSON
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/903a6e15a48e6788.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/claude-md-commands.ts:182
}
}
} catch (error) {
logger.warn('CLAUDE_MD', 'Failed to parse files_modified JSON', { error: error instanceof Error ? error.message : String(error) });
}
}
if (obs.files_read) {
try {
const read = JSON.parse(obs.files_read);
if (Array.isArray(read)) {
for (const file of read) {
if (isDirectChild(file, relativeFolder)) {
return path.basename(file);
}
}
}
} catch (error) {
logger.warn('CLAUDE_MD', 'Failed to parse files_read JSON', { error: error instanceof Error ? error.message : String(error) });
}
}
return 'General';
}
function formatObservationsForClaudeMd(observations: ObservationRow[], folderPath: string): string {
const lines: string[] = [];
lines.push('# Recent Activity');
lines.push('');
lines.push('<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->');
lines.push('');
if (observations.length === 0) {
lines.push('*No recent activity*');
return lines.join('\n');
}
View on GitHub (pinned to d8bc9755e7)