thedotmack/claude-mem · error · Error
Backfill failed
Error message
Backfill failed: ${error instanceof Error ? error.message : String(error)} What it means
ChromaSync.ensureBackfilled runs the backfill pipeline to bring Chroma up to the persisted watermarks. If runBackfillPipeline throws for any reason, the error is logged and re-thrown wrapped as 'Backfill failed: <cause>'. The wrapper discards the original stack, so the inner message is the only diagnostic carried to the caller.
Solutions
- Read the inner message after 'Backfill failed:' to identify the root cause (connection lost, queue full, etc.) and fix that first.
- Check Chroma MCP server availability and restart it if unreachable.
- Delete/reset the stored watermarks (ChromaSyncState) if they are inconsistent, forcing a clean re-backfill.
- Retry the backfill after the connection recovers; backfill is idempotent up to the watermark.
- If the wrapper hides the stack too often, log/rethrow the original error object instead of a new Error.
Example fix
// before (in ChromaSync.ts)
throw new Error(`Backfill failed: ${error instanceof Error ? error.message : String(error)}`);
// after: preserve cause for debugging
throw new Error(`Backfill failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error }); Defensive patterns
Strategy: retry
Validate before calling
// pre-checks before ensureBackfilled
if (!chromaServerHealthy()) throw new Error('Chroma unreachable; fix server before backfill');
const watermarks = ChromaSyncState.get(project);
if (!watermarks || typeof watermarks !== 'object') resetWatermarks(project); Try / catch
try {
await chromaSync.ensureBackfilled(store, project);
} catch (e) {
logger.error('backfill failed', { cause: e });
const rootCause = String(e.message).replace(/^Backfill failed: /, '');
await scheduleRetryWithBackoff(() => chromaSync.ensureBackfilled(store, project));
} Prevention
- Check Chroma MCP health before starting backfill
- Keep the original error as { cause } when wrapping for diagnosis
- Make backfill retries scheduled and idempotent via watermarks
- Alert on repeated 'Backfill failed' messages per project
When it happens
Trigger: Any failure inside runBackfillPipeline: Chroma unavailable, MCP mutation errors, queue-full/cancelled errors (130/131), or DB read failures while walking sessions since the watermark.
Common situations: Chroma MCP server down during startup backfill, network drop mid-backfill, corrupted or too-new watermark state, or mutation backpressure aborting the pipeline.
Related errors
- Chroma unavailable before write; leaving documents unsynced
- Observation watermark bump skipped — partial write
- Observation watermark bump skipped — partial write, row…
- Prompt watermark bump skipped — write failed
- Prompt watermark bump skipped — write failed, row marked…
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/7ddbdcd5faf329de.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sync/ChromaSync.ts:775
logger.info('CHROMA_SYNC', 'Bootstrapped watermarks from Chroma', {
project,
watermarks: ChromaSyncState.get(project)
});
}
async ensureBackfilled(project: string, store: SessionStore): Promise<void> {
logger.info('CHROMA_SYNC', 'Starting smart backfill', { project });
await this.ensureCollectionExists();
this.backfillAborted = false;
const watermarks = ChromaSyncState.get(project);
try {
await this.runBackfillPipeline(store, project, watermarks);
} catch (error) {
logger.error('CHROMA_SYNC', 'Backfill failed', { project }, error instanceof Error ? error : new Error(String(error)));
throw new Error(`Backfill failed: ${error instanceof Error ? error.message : String(error)}`);
}
}
private async runBackfillPipeline(
db: SessionStore,
backfillProject: string,
watermarks: ProjectWatermarks
): Promise<void> {
const observationDocs = await this.backfillObservations(db, backfillProject, watermarks.observations);
if (this.backfillAborted) {
return;
}
const summaryDocs = await this.backfillSummaries(db, backfillProject, watermarks.summaries);
if (this.backfillAborted) {
return;
}
const promptDocs = await this.backfillPrompts(db, backfillProject, watermarks.prompts);
if (this.backfillAborted) {View on GitHub (pinned to d8bc9755e7)