{"record":{"id":"05379f592c572818","repo":"thedotmack/claude-mem","slug":"chroma-query-failed-connection-lost-errormess","errorCode":null,"errorMessage":"Chroma query failed - connection lost: ${errorMessage}","messagePattern":"Chroma query failed - connection lost: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sync/ChromaSync.ts","lineNumber":1012,"sourceCode":"        n_results: limit,\n        ...(whereFilter && { where: whereFilter }),\n        include: ['documents', 'metadatas', 'distances']\n      });\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : String(error);\n\n      const isConnectionError =\n        errorMessage.includes('ECONNREFUSED') || // [ANTI-PATTERN IGNORED]: ChromaMcpManager.callTool re-wraps transport failures as plain Errors, so the Node error code only survives in the message text; the full error object is logged below.\n        errorMessage.includes('ENOTFOUND') || // [ANTI-PATTERN IGNORED]: same MCP transport re-wrapping as above; no structured code field is available on the re-wrapped error.\n        errorMessage.includes('fetch failed') || \n        errorMessage.includes('subprocess closed') || \n        errorMessage.includes('timed out'); \n\n      if (isConnectionError) {\n        this.collectionCreated = false;\n        logger.error('CHROMA_SYNC', 'Connection lost during query',\n          { project: this.project, query }, error as Error);\n        throw new Error(`Chroma query failed - connection lost: ${errorMessage}`);\n      }\n\n      logger.error('CHROMA_SYNC', 'Query failed', { project: this.project, query }, error as Error);\n      throw error;\n    }\n\n    return this.deduplicateQueryResults(results);\n  }\n\n  private deduplicateQueryResults(results: any): { ids: number[]; distances: number[]; metadatas: any[] } {\n    const ids: number[] = [];\n    const seen = new Set<string>();\n    const docIds = results?.ids?.[0] || [];\n    const rawMetadatas = results?.metadatas?.[0] || [];\n    const rawDistances = results?.distances?.[0] || [];\n\n    const metadatas: any[] = [];\n    const distances: number[] = [];","sourceCodeStart":994,"sourceCodeEnd":1030,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/sync/ChromaSync.ts#L994-L1030","documentation":"Thrown by ChromaSync.queryChroma when the chroma_query_documents call fails and the error message contains a connection-loss signature: 'ECONNREFUSED', 'ENOTFOUND', 'fetch failed', 'subprocess closed', or 'timed out'. collectionCreated is reset to false (so the next ensureCollectionExists re-creates) and the error is rethrown as a plain Error. The code comments note an anti-pattern: ChromaMcpManager re-wraps transport failures as plain Errors, so detection must substring-match the message text instead of reading an error code.","triggerScenarios":"chroma_query_documents threw; the thrown message includes one of the network/subprocess signatures — most commonly because chroma-mcp transport died (error 104), the subprocess was closed, or a fetch to the embedded chroma timed out.","commonSituations":"Chroma subprocess crashed under load; the OS refused a connection (port gone because subprocess exited); a slow query exceeded the timeout; the machine briefly lost loopback connectivity; chroma-mcp was OOM-killed during a large query.","solutions":["Confirm chroma-mcp is alive (isHealthy / probeSemanticSearch) and let ensureConnected/prewarm restart it.","Reduce query cost (smaller n_results / limit, tighter whereFilter) to avoid the 'timed out' path.","Because collectionCreated is reset, expect a re-create on the next call — ensure the data dir is writable.","Investigate memory pressure / OOM kills if 'subprocess closed' recurs.","Retry the query after a short backoff; this error is inherently transient."],"exampleFix":"// before: query surfaces a fatal-looking connection error\nconst r = await chromaSync.queryChroma(q, 10);\n// after: treat the connection-lost signature as transient\ntry { return await chromaSync.queryChroma(q, 10); }\ncatch (e) { if (/connection lost/.test(e.message)) { await sleep(500); return retry(); } throw e; }","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isQueryConnectionLost(e: unknown): boolean {\n  return e instanceof Error && /Chroma query failed - connection lost/i.test(e.message);\n}","tryCatchPattern":"try { return await chromaSync.queryChroma(q, limit, whereFilter); }\ncatch (e) {\n  if (isQueryConnectionLost(e)) { await sleep(500); return await chromaSync.queryChroma(q, limit, whereFilter); }\n  throw e;\n}","preventionTips":["Reduce query cost (smaller limit, tighter whereFilter) to avoid the 'timed out' signature.","Keep chroma-mcp healthy and memory-safe to avoid 'subprocess closed'.","Expect collectionCreated to be reset after this error; ensure the data dir is writable for re-create.","Treat this error as transient and retry with backoff."],"tags":["chroma","connection","query","transient","vector-search"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}