{"record":{"id":"8d23d7534fb7730e","repo":"thedotmack/claude-mem","slug":"invalid-transcript-watch-config-resolvedpath","errorCode":null,"errorMessage":"Invalid transcript watch config: ${resolvedPath}","messagePattern":"Invalid transcript watch config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/transcripts/config.ts","lineNumber":73,"sourceCode":"\nexport function expandHomePath(inputPath: string): string {\n  if (!inputPath) return inputPath;\n  // Shared expandTilde/expandHome leave `~user/...` alone (resolving another\n  // user's home is out of scope). The old inline version sliced one character\n  // off any leading tilde, so `~alice/transcripts` was rewritten to\n  // `<home>/alice/transcripts` and the watcher ingested nothing silently.\n  return expandTilde(inputPath);\n}\n\nexport function loadTranscriptWatchConfig(path = DEFAULT_CONFIG_PATH): TranscriptWatchConfig {\n  const resolvedPath = expandHomePath(path);\n  if (!existsSync(resolvedPath)) {\n    throw new Error(`Transcript watch config not found: ${resolvedPath}`);\n  }\n  const raw = readFileSync(resolvedPath, 'utf-8');\n  const parsed = JSON.parse(raw) as TranscriptWatchConfig;\n  if (!parsed.version || !parsed.watches) {\n    throw new Error(`Invalid transcript watch config: ${resolvedPath}`);\n  }\n  if (!parsed.stateFile) {\n    parsed.stateFile = DEFAULT_STATE_PATH;\n  }\n  return parsed;\n}\n\nexport function writeSampleConfig(path = DEFAULT_CONFIG_PATH): void {\n  const resolvedPath = expandHomePath(path);\n  const dir = dirname(resolvedPath);\n  if (!existsSync(dir)) {\n    mkdirSync(dir, { recursive: true });\n  }\n  writeFileSync(resolvedPath, JSON.stringify(SAMPLE_CONFIG, null, 2));\n}\n","sourceCodeStart":55,"sourceCodeEnd":89,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/transcripts/config.ts#L55-L89","documentation":"After reading and JSON-parsing the watch config, loadTranscriptWatchConfig validates its shape: a truthy version and a watches object/array are required. A file that parses as JSON but lacks these fields is rejected as structurally invalid, with the resolved path in the message.","triggerScenarios":"The config file at resolvedPath exists and is valid JSON but omits version or watches — e.g. an empty object {}, an outdated schema, or a file containing only stateFile.","commonSituations":"Hand-edited config missing required keys; config created by an older plugin version before schema changes; partial write/truncation that still left valid JSON; copying a template but not filling it in.","solutions":["Add the required fields: \"version\": 1 and a \"watches\" section to the config file.","Compare against the current documented schema and migrate an old-format config.","Validate the JSON keys (version, watches, stateFile) after editing.","Regenerate a fresh default config and re-apply your custom watches."],"exampleFix":"// before\n{ \"stateFile\": \"~/.claude-mem/watch-state.json\" }\n// after\n{ \"version\": 1, \"watches\": [{ \"path\": \"~/.claude/projects/**/transcript.jsonl\" }], \"stateFile\": \"~/.claude-mem/watch-state.json\" }","handlingStrategy":"validation","validationCode":"const raw = JSON.parse(readFileSync(p, 'utf8'));\nif (typeof raw.version !== 'number' || !raw.watches) throw new Error(`Invalid watch config at ${p}`);","typeGuard":"function isValidWatchConfig(v: unknown): v is TranscriptWatchConfig {\n  return typeof v === 'object' && v !== null && 'version' in v && 'watches' in v;\n}","tryCatchPattern":"try { const cfg = loadTranscriptWatchConfig(); } catch (e) { if (e.message.includes('Invalid transcript watch config')) { migrateOrRegenerateConfig(); } }","preventionTips":["Validate the config against the schema after every edit.","Version your config schema and provide migrations.","Keep a known-good template of the config in the repo."],"tags":["config","validation","schema"],"backgroundTag":"schema-validation-failed","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"}