thedotmack/claude-mem · warning
Unreadable chroma-sync-state.json, treating as empty
Error message
Unreadable chroma-sync-state.json, treating as empty
What it means
load() reads chroma-sync-state.json; if parsing fails (truncated/corrupt file, BOM/encoding issues not tolerated, invalid JSON), the state is treated as empty and the warning logged so the sync pipeline continues and rebuilds watermarks via backfill.
Solutions
- Delete or rename the corrupt ~/.claude-mem/chroma-sync-state.json; it will be recreated empty.
- Let the next backfill rebuild watermarks from SQLite (automatic).
- Restore the file from backup if you need prior watermark state to avoid a full re-sync.
- Check disk space and that no crash occurs mid-write (atomic write with temp file + rename).
Defensive patterns
Strategy: fallback
Validate before calling
import { readFileSync } from 'fs';
function stateFileIsParsable(path: string): boolean {
try { JSON.parse(readFileSync(path, 'utf8')); return true; } catch { return false; }
} Type guard
const isWatermarkState = (v: unknown): v is Record<string, Partial<ProjectWatermarks>> => typeof v === 'object' && v !== null && !Array.isArray(v);
Try / catch
try { parsed = readJsonFileWithBom(path); }
catch (e) {
logger.warn('state file unreadable; treating as empty', { path }, e);
cache = {};
} Prevention
- Write state atomically (temp file + rename)
- Restore state files from backup after crashes instead of deleting silently
- Validate state JSON after manual edits
- Monitor disk space on the state directory
When it happens
Trigger: The state file is truncated by a crash mid-write, contains invalid JSON from manual editing, or readJsonFileWithBom throws for any IO/parse reason.
Common situations: Machine crash/power loss while the file was being written, disk-full during write, manual edits with syntax errors, sync tools corrupting the file.
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.
Related errors
- SyncApply: invalid op seq=
- canonical content
- Expected JSON array in observation list field, using plain…
- mutation body is not JSON
- mutation body must be an object
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/74b1d3ee0fbae35e.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sync/ChromaSyncState.ts:72
}
return normalized;
}
function load(): Record<string, ProjectWatermarks> {
if (cache) return cache;
const path = statePath();
if (!existsSync(path)) {
cache = {};
return cache;
}
let parsed: Record<string, Partial<ProjectWatermarks>>;
try {
parsed = readJsonFileWithBom<Record<string, Partial<ProjectWatermarks>>>(path);
} catch (error) {
// A truncated or corrupt state file must not abort the sync pipeline. Treat
// it as empty and rebuild from the SQLite watermarks on the next backfill.
logger.warn('CHROMA_SYNC', 'Unreadable chroma-sync-state.json, treating as empty', {
path
}, error instanceof Error ? error : new Error(String(error)));
cache = {};
return cache;
}
const normalized: Record<string, ProjectWatermarks> = {};
for (const [project, marks] of Object.entries(parsed)) {
normalized[project] = normalizeProjectWatermarks(marks);
}
cache = normalized;
return cache;
}
function persist(): void {
if (!cache) return;
writeJsonFileAtomic(statePath(), cache);
}
View on GitHub (pinned to d8bc9755e7)