thedotmack/claude-mem · warning · ChromaUnavailableError
chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BAC
Error message
chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BACKOFF_MS - timeSinceLastFailure) / 1000)}s remaining) What it means
ChromaMcpManager is a singleton that backs off for RECONNECT_BACKOFF_MS (10s) after a connection attempt fails. ensureConnected() computes timeSinceLastFailure; if a failure happened within the backoff window, it throws ChromaUnavailableError (HTTP 503, code CHROMA_UNAVAILABLE) with the remaining seconds rather than hammering chroma-mcp. This protects a struggling subprocess and downstream callers see a typed unavailable error they can degrade on.
Source
Thrown at src/services/sync/ChromaMcpManager.ts:125
}
static getInstance(): ChromaMcpManager {
if (!ChromaMcpManager.instance) {
ChromaMcpManager.instance = new ChromaMcpManager();
}
return ChromaMcpManager.instance;
}
private async ensureConnected(): Promise<void> {
await this.waitForUnexpectedCloseCleanup();
if (this.connected && this.client) {
return;
}
const timeSinceLastFailure = Date.now() - this.lastConnectionFailureTimestamp;
if (this.lastConnectionFailureTimestamp > 0 && timeSinceLastFailure < RECONNECT_BACKOFF_MS) {
throw new ChromaUnavailableError(`chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BACKOFF_MS - timeSinceLastFailure) / 1000)}s remaining)`);
}
if (this.connecting) {
await this.connecting;
return;
}
this.connecting = this.connectInternal();
try {
await this.connecting;
} catch (error) {
if (error instanceof ChromaMcpConnectionCancelledError) {
logger.debug('CHROMA_MCP', 'Connection attempt cancelled during shutdown');
throw error;
}
this.lastConnectionFailureTimestamp = Date.now();
if (error instanceof Error) {
logger.error('CHROMA_MCP', 'Connection attempt failed', {}, error);View on GitHub (pinned to d768ba3643)
Solutions
- Wait the number of seconds shown in the message, then retry — the backoff is short (10s).
- Address the root connection failure (see the preceding CHROMA_MCP 'Connection attempt failed' log entry): install uvx, fix the data dir, free resources.
- If vector search is optional, catch ChromaUnavailableError and fall back to FTS/local search.
- Reduce parallel search fan-out so fewer callers pile up inside the backoff window.
Example fix
// before
const results = await chroma.search(query); // throws during backoff
// after — treat unavailable as non-fatal
catch (e) {
if (e instanceof ChromaUnavailableError) {
return await ftsSearch(query); // fallback
}
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// Backoff-aware caller: don't even attempt within the backoff window.
function backoffSecondsRemaining(lastFailAt: number, backoffMs = 10_000): number {
if (lastFailAt <= 0) return 0;
const remaining = backoffMs - (Date.now() - lastFailAt);
return remaining > 0 ? Math.ceil(remaining / 1000) : 0;
} Type guard
import { ChromaUnavailableError } from '../worker/search/errors.js';
function isChromaUnavailable(e: unknown): boolean {
return e instanceof ChromaUnavailableError;
} Try / catch
import { ChromaUnavailableError } from '../worker/search/errors.js';
async function searchWithFallback(q: string) {
try {
return await chroma.search(q);
} catch (e) {
if (e instanceof ChromaUnavailableError) {
return await ftsSearch(q); // vector search optional -> degrade
}
throw e;
}
} Prevention
- Treat ChromaUnavailableError as non-fatal and fall back to FTS/local search.
- Fix the underlying connection failure (see CHROMA_MCP logs) rather than retrying blindly.
- Space out parallel searches to avoid piling up inside the 10s backoff window.
When it happens
Trigger: Any chroma operation (vector search/upsert via the manager) is attempted within 10 seconds of the previous connection failure. lastConnectionFailureTimestamp was set because connectInternal() rejected (uvx missing, prewarm timeout, MCP handshake failure, etc.).
Common situations: chroma-mcp repeatedly fails to start (uvx/uv not installed, model download slow, port/stderr issues) and every subsequent search within 10s hits the backoff; a transient failure just occurred and a burst of parallel searches all see backoff; the worker retries too aggressively.
Related errors
- Chroma query failed - connection lost: ${errorMessage}
- 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
- Unable to remove stale Chroma writer lock at ${lockPath}: ${
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/1283be21413780b6.
Report an issue: GitHub.