thedotmack/claude-mem · warning · ChromaUnavailableError

Chroma mutation queue is full (${this.pendingMutationCalls}/

Error message

Chroma mutation queue is full (${this.pendingMutationCalls}/${this.maxPendingMutationCalls}); deferring "${toolName}" to a later backfill

What it means

Thrown by enqueueMutation when a new mutation tool call would exceed the in-flight cap: pendingMutationCalls >= maxPendingMutationCalls. It is a ChromaUnavailableError (503) by design — the manager deliberately defers the overflow mutation to a later backfill rather than queuing unbounded work. The mutation is not lost; it will be reconciled by ChromaSync.ensureBackfilled on a subsequent run using watermarks.

Source

Thrown at src/services/sync/ChromaMcpManager.ts:795

      if (parseError instanceof Error) {
        logger.debug('CHROMA_MCP', 'Non-JSON response from tool, returning null', {
          toolName,
          textPreview: firstTextContent.text.slice(0, 100)
        });
      }
      return null;
    }
  }

  private async enqueueMutation<T>(operation: () => Promise<T>, toolName: string): Promise<T> {
    if (this.pendingMutationCalls >= this.maxPendingMutationCalls) {
      const message = `Chroma mutation queue is full (${this.pendingMutationCalls}/${this.maxPendingMutationCalls}); deferring "${toolName}" to a later backfill`;
      logger.warn('CHROMA_MCP', message, {
        toolName,
        pendingMutations: this.pendingMutationCalls,
        maxPendingMutations: this.maxPendingMutationCalls
      });
      throw new ChromaUnavailableError(message);
    }

    this.pendingMutationCalls += 1;
    const enqueuedGeneration = this.connectionGeneration;
    const run = this.mutationTail
      .catch(() => undefined)
      .then(async () => {
        if (enqueuedGeneration !== this.connectionGeneration) {
          throw new ChromaMcpConnectionCancelledError('queued chroma-mcp mutation cancelled during shutdown');
        }
        return operation();
      });

    this.mutationTail = run.then(() => undefined, () => undefined);

    try {
      return await run;
    } finally {

View on GitHub (pinned to d768ba3643)

Solutions

  1. Treat the error as transient: the mutation will be applied by the next backfill pass, so it is safe to log and continue.
  2. Reduce ingestion burstiness — batch/coalesce writes so fewer individual mutation calls are issued.
  3. Raise maxPendingMutationCalls if your workload legitimately needs a deeper in-flight queue.
  4. Investigate why chroma-mcp is slow (disk I/O, large collection) so the queue drains faster.
  5. Ensure ensureBackfilled is scheduled periodically so deferred mutations actually get reconciled.

Example fix

// before: caller treats full-queue 503 as a hard failure
await manager.callTool('chroma_upsert', args);
// after: caller recognizes the deferral and relies on backfill
try { await manager.callTool('chroma_upsert', args); }
catch (e) { if (e instanceof ChromaUnavailableError && /mutation queue is full/.test(e.message)) { log.warn('deferred to backfill'); } else throw e; }
Defensive patterns

Strategy: fallback

Type guard

function isMutationQueueFull(e: unknown): boolean {
  return e instanceof Error && /Chroma mutation queue is full.*deferring/i.test(e.message);
}

Try / catch

try { await manager.callTool('chroma_upsert', args); }
catch (e) {
  if (isMutationQueueFull(e)) { /* safe: backfill will reconcile later */ log.warn('mutation deferred to backfill'); return; }
  throw e;
}

Prevention

When it happens

Trigger: callTool is invoked for a mutation tool (matches CHROMA_MUTATION_TOOL_PATTERN) while serializeMutations is on, and pendingMutationCalls has already reached maxPendingMutationCalls because prior mutations are still running through the serialized mutationTail promise chain.

Common situations: A burst of indexing (many observations/summaries/prompts) arrives faster than chroma-mcp can apply them; chroma-mcp slow-down (disk/CPU) grows the queue; a backfill running in parallel with live ingestion saturates the queue.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/ec5055917cb71206. Report an issue: GitHub.