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

  1. Read the inner message after 'Backfill failed:' to identify the root cause (connection lost, queue full, etc.) and fix that first.
  2. Check Chroma MCP server availability and restart it if unreachable.
  3. Delete/reset the stored watermarks (ChromaSyncState) if they are inconsistent, forcing a clean re-backfill.
  4. Retry the backfill after the connection recovers; backfill is idempotent up to the watermark.
  5. 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

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


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)