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

  1. Delete or rename the corrupt ~/.claude-mem/chroma-sync-state.json; it will be recreated empty.
  2. Let the next backfill rebuild watermarks from SQLite (automatic).
  3. Restore the file from backup if you need prior watermark state to avoid a full re-sync.
  4. 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

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


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)