{"record":{"id":"05a976de76bd225a","repo":"thedotmack/claude-mem","slug":"chroma-unavailable","errorCode":"CHROMA_UNAVAILABLE","errorMessage":"Chroma query failed: ${errorObj.message}","messagePattern":"Chroma query failed: (.+?)","errorType":"http","errorClass":"ChromaUnavailableError","httpStatus":503,"severity":"error","filePath":"src/services/worker/search/SearchOrchestrator.ts","lineNumber":68,"sourceCode":"    options: NormalizedParams\n  ): Promise<StrategySearchResult> {\n    if (!options.query) {\n      logger.debug('SEARCH', 'Orchestrator: Filter-only query, using SQLite', {});\n      return await this.sqliteStrategy.search(options);\n    }\n\n    if (this.chromaStrategy) {\n      logger.debug('SEARCH', 'Orchestrator: Using Chroma semantic search', {});\n      try {\n        const chromaResult = await this.chromaStrategy.search(options);\n        if (options.platformSource && this.isEmptyResult(chromaResult)) {\n          logger.debug('SEARCH', 'Orchestrator: platform-scoped Chroma search returned zero matches; falling back to SQLite', {});\n          return await this.sqliteStrategy.search(options);\n        }\n        return chromaResult;\n      } catch (error) {\n        const errorObj = error instanceof Error ? error : new Error(String(error));\n        throw new ChromaUnavailableError(\n          `Chroma query failed: ${errorObj.message}`,\n          errorObj\n        );\n      }\n    }\n\n    logger.debug('SEARCH', 'Orchestrator: Chroma not configured', {});\n    return {\n      results: { observations: [], sessions: [], prompts: [] },\n      usedChroma: false,\n      strategy: 'sqlite'\n    };\n  }\n\n  private isEmptyResult(result: StrategySearchResult): boolean {\n    return result.results.observations.length === 0\n      && result.results.sessions.length === 0\n      && result.results.prompts.length === 0;","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/worker/search/SearchOrchestrator.ts#L50-L86","documentation":"Thrown by SearchOrchestrator.executeWithFallback when the ChromaSearchStrategy.search call rejects. The original error is wrapped in a ChromaUnavailableError (an AppError, HTTP 503, code CHROMA_UNAVAILABLE) preserving the cause message. It signals the semantic-search backend is unreachable or malfunctioning; callers can fall back to SQLite.","triggerScenarios":"chromaStrategy.search(options) throws — e.g., Chroma server down, collection missing, embedding error, network refusal. Only reached when this.chromaStrategy is non-null (chromaSync configured).","commonSituations":"Chroma server not running or unreachable; Chroma collection never synced/embedded; uv/Python dependency for Chroma missing; embedding model misconfigured; connection timeout to Chroma.","solutions":["Verify the Chroma server/process is running and reachable (check ~/.claude-mem/chroma).","Ensure uv (Python) is installed so Chroma can start; check sync logs (ChromaSync).","Catch ChromaUnavailableError in the caller and fall back to SQLite search (strategy 'sqlite').","Re-run ChromaSync to populate/re-embed collections if the collection is empty or missing."],"exampleFix":"// before\nconst result = await orchestrator.search(args);\n\n// after\nimport { ChromaUnavailableError } from './errors';\ntry {\n  const result = await orchestrator.search(args);\n} catch (err) {\n  if (err instanceof ChromaUnavailableError) {\n    logger.warn('SEARCH', 'Chroma down, falling back to SQLite');\n    return sqliteFallback(args);\n  }\n  throw err;\n}","handlingStrategy":"fallback","validationCode":"// Pre-flight: only use Chroma if it's healthy\nasync function isChromaAvailable(chromaSync: ChromaSync | null): Promise<boolean> {\n  if (!chromaSync) return false;\n  try { await chromaSync.ping(); return true; } catch { return false; }\n}","typeGuard":"import { ChromaUnavailableError } from './errors';\nfunction isChromaUnavailable(e: unknown): e is ChromaUnavailableError {\n  return e instanceof ChromaUnavailableError;\n}","tryCatchPattern":"try {\n  return await orchestrator.search(args);\n} catch (err) {\n  if (err instanceof ChromaUnavailableError) {\n    logger.warn('SEARCH', 'Chroma unavailable, using SQLite fallback', { cause: err.message });\n    return sqliteStrategy.search(normalizeParams(args));\n  }\n  throw err;\n}","preventionTips":["Monitor Chroma health and surface outages before search requests hit it.","Keep ChromaSync populated so collections exist for queries.","Always implement a SQLite fallback for ChromaUnavailableError in search callers."],"tags":["search","chroma","semantic-search","http-503","fallback"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}