thedotmack/claude-mem · warning

Backfill marker read failed; treating backfill as complete t

Error message

Backfill marker read failed; treating backfill as complete to avoid duplicate sends

What it means

isBackfillComplete() reads the marker file via readJsonSafe, which already maps missing or corrupt-JSON files to null; this catch fires only on hard IO errors (EACCES, EPERM, EIO). Because PostHog events cannot be selectively deleted, the fail-safe default is 'backfill complete' — skip it — since a telemetry gap is preferred over duplicate sends.

Source

Thrown at src/services/telemetry/backfill.ts:168

 * backfilled installs re-run and pick up the enriched rollup keys — without it,
 * the one-shot marker would pin them forever to whatever shipped when they
 * first backfilled (the read_tokens / tokens_saved_vs_naive series would only
 * ever reach fresh installs).
 *
 * A corrupt marker file still counts as complete: a marker was written at some
 * point, and duplicate sends are worse than a gap (PostHog data cannot be
 * selectively deleted). A marker missing the `version` field is a legacy
 * version-1 marker.
 */
function isBackfillComplete(): boolean {
  try {
    const marker = readJsonSafe<Partial<BackfillMarker> | null>(getBackfillMarkerPath(), null);
    if (marker === null) return false;
    const version = typeof marker.version === 'number' ? marker.version : 1;
    return version >= BACKFILL_VERSION;
  } catch (error) {
    const err = error instanceof Error ? error : new Error(String(error));
    logger.warn('SYSTEM', 'Backfill marker read failed; treating backfill as complete to avoid duplicate sends', {}, err);
    return true;
  }
}

function writeBackfillMarker(marker: BackfillMarker): void {
  const dataDir = resolveDataDir();
  mkdirSync(dataDir, { recursive: true });
  writeFileSync(getBackfillMarkerPath(), JSON.stringify(marker, null, 2) + '\n');
}

/**
 * Per-day anonymous activity rollups, bucketed by UTC day. Only whole UTC
 * days inside `installDay <= day <= lastFullDay` are included, comparing
 * day strings (YYYY-MM-DD compares lexicographically) — never raw epochs, so
 * no partial day can ever ship. Rows below PROJECT_EPOCH_FLOOR are ignored.
 *
 * Each query block is independently best-effort (a missing table/column on an
 * older install skips that block's keys, never throws) — same pattern as

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Fix read permissions on the marker file inside the claude-mem data dir
  2. If the file was hand-edited, verify it is valid JSON with jq
  3. If the marker is truly lost and duplicate analytics are acceptable, delete it so the deterministic backfill reruns
  4. Otherwise take no action — the historical backfill is simply skipped
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: The marker file exists but is unreadable: permission changes, the file locked by antivirus or backup software (common on Windows), a failing disk, or exotic filesystem errors.

Common situations: Data dir restored with wrong ownership; enterprise AV holding files; data dir on a NAS.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/1a49df31842a0a53. Report an issue: GitHub.