thedotmack/claude-mem · error · Error
Invalid transcript watch config: ${resolvedPath}
Error message
Invalid transcript watch config: ${resolvedPath} What it means
Thrown by loadTranscriptWatchConfig when the config file exists and parses as JSON but is missing the required `version` or `watches` field. The loader requires both keys to consider the config valid; their absence means the file is structurally incomplete.
Source
Thrown at src/services/transcripts/config.ts:72
}
export function expandHomePath(inputPath: string): string {
if (!inputPath) return inputPath;
if (inputPath.startsWith('~')) {
return join(homedir(), inputPath.slice(1));
}
return inputPath;
}
export function loadTranscriptWatchConfig(path = DEFAULT_CONFIG_PATH): TranscriptWatchConfig {
const resolvedPath = expandHomePath(path);
if (!existsSync(resolvedPath)) {
throw new Error(`Transcript watch config not found: ${resolvedPath}`);
}
const raw = readFileSync(resolvedPath, 'utf-8');
const parsed = JSON.parse(raw) as TranscriptWatchConfig;
if (!parsed.version || !parsed.watches) {
throw new Error(`Invalid transcript watch config: ${resolvedPath}`);
}
if (!parsed.stateFile) {
parsed.stateFile = DEFAULT_STATE_PATH;
}
return parsed;
}
export function writeSampleConfig(path = DEFAULT_CONFIG_PATH): void {
const resolvedPath = expandHomePath(path);
const dir = dirname(resolvedPath);
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
writeFileSync(resolvedPath, JSON.stringify(SAMPLE_CONFIG, null, 2));
}
View on GitHub (pinned to d768ba3643)
Solutions
- Open the resolved path and add the missing top-level fields: `version` (number, currently 1) and `watches` (array, possibly empty).
- If unsure of the shape, back up the bad file and regenerate via writeSampleConfig() then re-apply your custom watches.
- Validate the JSON with a linter to rule out a silent parse into the wrong structure.
- Upgrade-stale configs: migrate old fields into the current version/watches schema.
Example fix
// before: { "stateFile": "/..." } // missing version + watches -> throws
// after: { "version": 1, "watches": [], "stateFile": "/..." } Defensive patterns
Strategy: validation
Validate before calling
function isValidConfig(c: unknown): c is TranscriptWatchConfig {
return typeof c === 'object' && c !== null
&& typeof (c as any).version === 'number'
&& Array.isArray((c as any).watches);
}
// usage:
const parsed = JSON.parse(readFileSync(resolved, 'utf-8'));
if (!isValidConfig(parsed)) throw new Error('config missing version or watches'); Type guard
function isTranscriptWatchConfig(c: unknown): c is TranscriptWatchConfig {
if (typeof c !== 'object' || c === null) return false;
const o = c as Record<string, unknown>;
return typeof o.version === 'number' && Array.isArray(o.watches);
} Try / catch
try { config = loadTranscriptWatchConfig(path); }
catch (e) {
if (e instanceof Error && e.message.startsWith('Invalid transcript watch config')) {
// back up and regenerate
writeSampleConfig(path); config = loadTranscriptWatchConfig(path); return;
}
throw e;
} Prevention
- Validate version + watches presence right after JSON.parse before trusting the shape.
- Keep a known-good sample (writeSampleConfig) to fall back to on structural failure.
- Add a JSON-schema check in CI for committed transcript configs.
When it happens
Trigger: loadTranscriptWatchConfig: existsSync passes, readFileSync + JSON.parse succeeds, but `parsed.version` or `parsed.watches` is falsy. Note JSON.parse throwing a SyntaxError would surface as a separate unhandled parse error before this check.
Common situations: Hand-edited config with a typo (e.g. `watch` instead of `watches`), a partial/old config schema from a prior version that lacked `watches`, an empty `{}` file, or a file overwritten by another tool. The message names the resolved path for inspection.
Related errors
- Invalid CLAUDE_MEM_WORKER_PORT in settings.json: missing
- Invalid CLAUDE_MEM_WORKER_PORT in settings.json: ${rawPort}
- Unknown Claude model: ${options.model}. Allowed: ${[...allow
- CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/8d23d7534fb7730e.
Report an issue: GitHub.