{"record":{"id":"1283be21413780b6","repo":"thedotmack/claude-mem","slug":"chroma-mcp-connection-in-backoff-math-ceil-reconnect-backoff","errorCode":null,"errorMessage":"chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BACKOFF_MS - timeSinceLastFailure) / 1000)}s remaining)","messagePattern":"chroma-mcp connection in backoff \\((.+?)s remaining\\)","errorType":"exception","errorClass":"ChromaUnavailableError","httpStatus":null,"severity":"warning","filePath":"src/services/sync/ChromaMcpManager.ts","lineNumber":167,"sourceCode":"  }\n\n  static getInstance(): ChromaMcpManager {\n    if (!ChromaMcpManager.instance) {\n      ChromaMcpManager.instance = new ChromaMcpManager();\n    }\n    return ChromaMcpManager.instance;\n  }\n\n  private async ensureConnected(): Promise<void> {\n    await this.waitForUnexpectedCloseCleanup();\n\n    if (this.connected && this.client) {\n      return;\n    }\n\n    const timeSinceLastFailure = Date.now() - this.lastConnectionFailureTimestamp;\n    if (this.lastConnectionFailureTimestamp > 0 && timeSinceLastFailure < RECONNECT_BACKOFF_MS) {\n      throw new ChromaUnavailableError(`chroma-mcp connection in backoff (${Math.ceil((RECONNECT_BACKOFF_MS - timeSinceLastFailure) / 1000)}s remaining)`);\n    }\n\n    if (this.connecting) {\n      await this.connecting;\n      return;\n    }\n\n    this.connecting = this.connectInternal();\n    try {\n      await this.connecting;\n    } catch (error) {\n      if (error instanceof ChromaMcpConnectionCancelledError) {\n        logger.debug('CHROMA_MCP', 'Connection attempt cancelled during shutdown');\n        throw error;\n      }\n      this.lastConnectionFailureTimestamp = Date.now();\n      if (error instanceof ChromaUnavailableError) {\n        // Chroma being unavailable is transient and already handled downstream","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/sync/ChromaMcpManager.ts#L149-L185","documentation":"ensureConnected refuses to (re)establish the chroma-mcp connection while a previous failed attempt is still within RECONNECT_BACKOFF_MS, throwing ChromaUnavailableError with the remaining seconds. This prevents hammering a broken chroma-mcp subprocess with reconnect attempts.","triggerScenarios":"Calling callToolUnqueued (or anything that reaches ensureConnected) within RECONNECT_BACKOFF_MS of the last failed connection attempt (lastConnectionFailureTimestamp > 0).","commonSituations":"A vector-search write/retry loop retrying faster than the backoff window after chroma-mcp crashed, failed to spawn (missing uvx), or timed out during handshake; system clock skew making timeSinceLastFailure appear small.","solutions":["Wait until the reported backoff seconds elapse, then retry the operation.","Fix the underlying chroma-mcp startup failure (check uvx availability, Chroma mode settings, logs) so the next connect succeeds.","If shutdown or a settings change should reset the backoff, ensure dispose/reset clears lastConnectionFailureTimestamp.","Catch ChromaUnavailableError in the caller and skip/dequeue the write until the backoff expires."],"exampleFix":"// before\nawait manager.callToolUnqueued('query', args); // throws during backoff\n// after\ntry {\n  await manager.callToolUnqueued('query', args);\n} catch (e) {\n  if (e instanceof ChromaUnavailableError) queueRetryLater(e); // retry after backoff\n  else throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await manager.callToolUnqueued(tool, args);\n} catch (e) {\n  if (e instanceof ChromaUnavailableError && e.message.includes('backoff')) {\n    await sleep(RECONNECT_BACKOFF_MS);\n    retryLater(args); // requeue instead of failing the write\n  } else throw e;\n}","preventionTips":["Respect the reported backoff seconds before retrying chroma operations.","Fix root startup failures (uvx, settings, data dir) instead of retrying into the backoff window.","Queue vector-search writes and drain them after the backoff expires."],"tags":["chroma","backoff","retry","mcp"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}