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
- Treat the error as transient: the mutation will be applied by the next backfill pass, so it is safe to log and continue.
- Reduce ingestion burstiness — batch/coalesce writes so fewer individual mutation calls are issued.
- Raise maxPendingMutationCalls if your workload legitimately needs a deeper in-flight queue.
- Investigate why chroma-mcp is slow (disk I/O, large collection) so the queue drains faster.
- 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
- Coalesce bursty writes into fewer mutation calls to stay under maxPendingMutationCalls.
- Schedule ensureBackfilled periodically so deferred mutations are reconciled.
- Tune maxPendingMutationCalls to your steady-state ingestion rate.
- Keep chroma-mcp healthy so the queue drains at full speed.
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
- Backfill failed: ${error instanceof Error ? error.message :
- chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BAC
- uvx executable not found for chroma-mcp (${uvxSpawnCommand})
- Unable to acquire Chroma writer lock at ${lockPath}: ${error
- Chroma writer lock at ${lockPath} is unreadable; refusing to
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/ec5055917cb71206.
Report an issue: GitHub.