{"record":{"id":"361275cdf2ccf331","repo":"thedotmack/claude-mem","slug":"failed-to-parse-files-modified-json","errorCode":null,"errorMessage":"Failed to parse files_modified JSON","messagePattern":"Failed to parse files_modified JSON","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/cli/claude-md-commands.ts","lineNumber":167,"sourceCode":"  const likePattern = `%\"${normalizedFolderPath}/%`;\n  const allMatches = db.prepare(sql).all(project, likePattern, likePattern, queryLimit) as ObservationRow[];\n\n  return allMatches.filter(obs => hasDirectChildFile(obs, relativeFolderPath)).slice(0, limit);\n}\n\nfunction extractRelevantFile(obs: ObservationRow, relativeFolder: string): string {\n  if (obs.files_modified) {\n    try {\n      const modified = JSON.parse(obs.files_modified);\n      if (Array.isArray(modified)) {\n        for (const file of modified) {\n          if (isDirectChild(file, relativeFolder)) {\n            return path.basename(file);\n          }\n        }\n      }\n    } catch (error) {\n      logger.warn('CLAUDE_MD', 'Failed to parse files_modified JSON', { error: error instanceof Error ? error.message : String(error) });\n    }\n  }\n\n  if (obs.files_read) {\n    try {\n      const read = JSON.parse(obs.files_read);\n      if (Array.isArray(read)) {\n        for (const file of read) {\n          if (isDirectChild(file, relativeFolder)) {\n            return path.basename(file);\n          }\n        }\n      }\n    } catch (error) {\n      logger.warn('CLAUDE_MD', 'Failed to parse files_read JSON', { error: error instanceof Error ? error.message : String(error) });\n    }\n  }\n","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/cli/claude-md-commands.ts#L149-L185","documentation":"extractRelevantFile tries to parse obs.files_modified as a JSON array to find a file directly under the target folder. If JSON.parse throws, this warning is logged and the function falls through to trying obs.files_read, ultimately returning the fallback label 'General'. The error is non-fatal by design.","triggerScenarios":"The observation's files_modified column contains invalid JSON — a raw comma-separated path list, an empty string that is not null, quoted-but-unterminated JSON, or binary/garbage data from a corrupt row.","commonSituations":"Rows written by older claude-mem versions with a different serialization; DB corruption or interrupted writes; observations created manually or by third-party tooling that wrote a plain string.","solutions":["Fix or regenerate the observation's files_modified value as a JSON array (JSON.stringify of string[])","Set the field to NULL instead of an empty/invalid string when there are no modified files","Re-run the summarize/import step so the observation is rewritten correctly","Check writer code paths to ensure every persist site serializes with JSON.stringify"],"exampleFix":"// before\nobs.files_modified = '';\n// after\nobs.files_modified = null; // or JSON.stringify([])","handlingStrategy":"validation","validationCode":"let modified: string[] = [];\ntry { const p = JSON.parse(obs.files_modified); if (Array.isArray(p)) modified = p; } catch { /* fallback */ }","typeGuard":"function asStringArray(v: unknown): string[] {\n  const p = typeof v === 'string' ? safeParse(v) : v;\n  return Array.isArray(p) ? p.filter((x): x is string => typeof x === 'string') : [];\n}","tryCatchPattern":"try { files = JSON.parse(obs.files_modified); } catch {\n  logger.warn('...', { raw: obs.files_modified?.slice(0, 100) });\n  files = [];\n}","preventionTips":["Serialize with JSON.stringify at every write site","Keep empty arrays as '[]' rather than empty strings","Validate rows after import/migration","Version-stamp observation rows so format changes are detectable"],"tags":["json","parsing","fallback"],"backgroundTag":"json-parse-error","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}