thedotmack/claude-mem · error · Error

Chroma query failed - connection lost

Error message

Chroma query failed - connection lost: ${errorMessage}

What it means

ChromaSync.query detects connection-class failures (the error message includes connection-loss indicators such as timeouts) while querying Chroma. It resets collectionCreated so the next call re-creates the collection, logs the failure, and throws a new Error 'Chroma query failed - connection lost: <msg>'. This signals that the Chroma connection must be re-established, not just retried blindly.

Solutions

  1. Retry the query after a short delay; collectionCreated was reset so the collection/connection is re-established automatically.
  2. Verify the Chroma server is running and reachable at the configured host/port.
  3. Add keep-alive or lower idle timeouts on proxies between the app and Chroma.
  4. Catch this error and trigger a re-probe/reconnect before resuming sync.
  5. Increase the query timeout if queries legitimately take longer than the server timeout.

Example fix

// before
const results = await chromaSync.query(project, queryText);
// after
let results;
try {
  results = await chromaSync.query(project, queryText);
} catch (e) {
  if (String(e.message).includes('connection lost')) {
    await sleep(1000);
    results = await chromaSync.query(project, queryText);
  } else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// health-check Chroma before heavy query loops
const healthy = await fetch(`${chromaBaseUrl}/api/v1/heartbeat`, { signal: AbortSignal.timeout(3000) }).then(r => r.ok).catch(() => false);
if (!healthy) await reconnectChroma();

Try / catch

try {
  results = await chromaSync.query(project, q);
} catch (e) {
  if (/Chroma query failed - connection lost/.test(e.message)) {
    await sleep(1000); results = await chromaSync.query(project, q); // collection is re-created
  } else throw e;
}

Prevention

When it happens

Trigger: A query() call against Chroma where the underlying error is a connection drop, socket error, or timeout (errorMessage includes the connection-error markers checked in isConnectionError).

Common situations: Chroma server restarted or OOM-killed mid-session, idle connection reaped by a proxy/load balancer, network partition between app and Chroma, or query exceeding server timeout.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/05379f592c572818. Report an issue: GitHub.

Appendix: source

Thrown at src/services/sync/ChromaSync.ts:1106

        n_results: limit,
        ...(whereFilter && { where: whereFilter }),
        include: ['documents', 'metadatas', 'distances']
      });
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);

      const isConnectionError =
        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.
        errorMessage.includes('ENOTFOUND') || // [ANTI-PATTERN IGNORED]: same MCP transport re-wrapping as above; no structured code field is available on the re-wrapped error.
        errorMessage.includes('fetch failed') || 
        errorMessage.includes('subprocess closed') || 
        errorMessage.includes('timed out'); 

      if (isConnectionError) {
        this.collectionCreated = false;
        logger.error('CHROMA_SYNC', 'Connection lost during query',
          { project: this.project, query }, error as Error);
        throw new Error(`Chroma query failed - connection lost: ${errorMessage}`);
      }

      logger.error('CHROMA_SYNC', 'Query failed', { project: this.project, query }, error as Error);
      throw error;
    }

    return this.deduplicateQueryResults(results);
  }

  private deduplicateQueryResults(results: any): { ids: number[]; distances: number[]; metadatas: any[] } {
    const ids: number[] = [];
    const seen = new Set<string>();
    const docIds = results?.ids?.[0] || [];
    const rawMetadatas = results?.metadatas?.[0] || [];
    const rawDistances = results?.distances?.[0] || [];

    const metadatas: any[] = [];
    const distances: number[] = [];

View on GitHub (pinned to d8bc9755e7)