thedotmack/claude-mem · error · ChromaUnavailableError
Chroma query failed
Error message
Chroma query failed: ${errorObj.message} What it means
The search orchestrator wraps any failure from the Chroma (vector) search strategy in a ChromaUnavailableError carrying the original message, so callers can distinguish 'Chroma is down/broken' from 'no results'. Note the orchestrator already falls back to SQLite only when Chroma returns zero matches — a thrown error propagates instead of falling back.
Solutions
- Check that the Chroma service is running and reachable (process, port, health endpoint)
- Catch ChromaUnavailableError at the call site and fall back to the SQLite strategy, mirroring the zero-match fallback
- Inspect the cause property (the wrapped original error) for the real failure — connection refused vs HTTP error vs embedding failure
- Verify the chroma index and embedding configuration are intact and dimensionally consistent
Example fix
// before
const results = await orchestrator.search(options); // throws if Chroma errors
// after
let results;
try {
results = await orchestrator.search(options);
} catch (err) {
if (err instanceof ChromaUnavailableError) {
results = await sqliteStrategy.search(options); // graceful degradation
} else {
throw err;
}
} Defensive patterns
Strategy: fallback
Validate before calling
import { existsSync } from 'fs';
// quick health check before issuing vector searches:
const chromaUp = existsSync(chromaDataDir); // plus a real ping/health call to the Chroma endpoint in production Type guard
function isChromaUnavailable(err: unknown): err is ChromaUnavailableError {
return err instanceof ChromaUnavailableError;
} Try / catch
try {
results = await orchestrator.search(options);
} catch (err) {
if (isChromaUnavailable(err)) {
logger.warn('Chroma unavailable, falling back to SQLite', { cause: err.cause?.message });
results = await sqliteStrategy.search(options);
} else {
throw err;
}
} Prevention
- Monitor the Chroma process/endpoint health and restart it on failure
- Always keep the SQLite strategy warm as a degradation path
- Inspect ChromaUnavailableError.cause for the real root cause before changing config
- Verify embedding dimensions and index integrity after model or Chroma version upgrades
When it happens
Trigger: Chroma HTTP query fails: Chroma server not running, connection refused, malformed query embedding, Chroma returning 4xx/5xx, or any non-Error thrown value in the chroma search path.
Common situations: Chroma subprocess (managed via uv/python) failed to start or crashed; port mismatch or stale CHROMA endpoint config after an upgrade; empty/corrupt chroma index directory; embedding dimension mismatch between index and query model.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- API key prompt cancelled — falling back to Claude provider.
- Backfill failed
- Chroma data dir is already owned by PID ; refusing to start…
- chroma-mcp call cancelled during shutdown
- chroma-mcp connection cancelled during shutdown
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/8b1bc75ad4bbc78b.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker/search/SearchOrchestrator.ts:68
options: NormalizedParams
): Promise<StrategySearchResult> {
if (!options.query) {
logger.debug('SEARCH', 'Orchestrator: Filter-only query, using SQLite', {});
return await this.sqliteStrategy.search(options);
}
if (this.chromaStrategy) {
logger.debug('SEARCH', 'Orchestrator: Using Chroma semantic search', {});
try {
const chromaResult = await this.chromaStrategy.search(options);
if (this.isEmptyResult(chromaResult)) {
logger.debug('SEARCH', 'Orchestrator: Chroma search returned zero matches; falling back to SQLite', {});
return await this.sqliteStrategy.search(options);
}
return chromaResult;
} catch (error) {
const errorObj = error instanceof Error ? error : new Error(String(error));
throw new ChromaUnavailableError(
`Chroma query failed: ${errorObj.message}`,
errorObj
);
}
}
logger.debug('SEARCH', 'Orchestrator: Chroma not configured', {});
return {
results: { observations: [], sessions: [], prompts: [] },
usedChroma: false,
strategy: 'sqlite'
};
}
private isEmptyResult(result: StrategySearchResult): boolean {
return result.results.observations.length === 0
&& result.results.sessions.length === 0
&& result.results.prompts.length === 0;View on GitHub (pinned to d8bc9755e7)