{"record":{"id":"34e538e42cf8eb0a","repo":"thedotmack/claude-mem","slug":"chroma-mcp-subprocess-closed-unexpectedly-applyin","errorCode":null,"errorMessage":"chroma-mcp subprocess closed unexpectedly, applying reconnect backoff","messagePattern":"chroma-mcp subprocess closed unexpectedly, applying reconnect backoff","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/sync/ChromaMcpManager.ts","lineNumber":319,"sourceCode":"    const currentTransport = this.transport;\n    // Captured HERE, while the child is alive and attached — not in the\n    // onclose handler below, which by definition runs after it has died.\n    const transportChild = (this.transport as unknown as { _process?: ChildProcess })._process;\n    const currentTracked = transportChild ? trackChild(transportChild) : null;\n    const currentTrackedPid = currentTracked?.pid;\n    this.transport.onclose = () => {\n      if (this.transport !== currentTransport) {\n        logger.debug('CHROMA_MCP', 'Ignoring stale onclose from previous transport');\n        return;\n      }\n      if (\n        this.connectionGeneration !== connectionGeneration ||\n        this.intentionallyClosingTransports.has(currentTransport as unknown as object)\n      ) {\n        logger.debug('CHROMA_MCP', 'Ignoring onclose from intentionally closed transport');\n        return;\n      }\n      logger.warn('CHROMA_MCP', 'chroma-mcp subprocess closed unexpectedly, applying reconnect backoff');\n      this.connected = false;\n      getSupervisor().unregisterProcess(CHROMA_SUPERVISOR_ID);\n      this.client = null;\n      this.transport = null;\n      this.lastConnectionFailureTimestamp = Date.now();\n\n      // Direct child (uvx) emitted close, but on Linux the grandchildren\n      // (uv/python/chroma-mcp) often outlive their parent because MCP SDK\n      // does not use process groups. Sweep the descendant tree using the\n      // captured PID — best-effort; pgrep returns nothing if everything\n      // already exited (#2313).\n      this.scheduleUnexpectedCloseCleanup(currentTracked);\n    };\n  }\n\n  private scheduleUnexpectedCloseCleanup(tracked: TrackedChild | null): void {\n    let cleanup: Promise<void>;\n    cleanup = this.cleanupUnexpectedCloseSubprocess(tracked).finally(() => {","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/8bc631a71a487424b866756e43a6efa4574cc66b/src/services/sync/ChromaMcpManager.ts#L301-L337","documentation":"The Chroma MCP client runs `chroma-mcp` (via uvx) as a stdio subprocess. When its transport closes while the connection is current, not intentionally being closed, and belongs to this connection generation, the manager marks itself disconnected, unregisters from the supervisor, and schedules a reconnect with backoff plus a best-effort descendant sweep (on Linux the uv/python grandchildren outlive uvx — issue #2313).","triggerScenarios":"The chroma-mcp subprocess dies — Python crash, missing uv/uvx, OOM kill, or stdio EOF — while the manager considered the connection live.","commonSituations":"Broken uv installation, incompatible chroma-mcp version, memory pressure killing Python, or system sleep/resume closing the pipes.","solutions":["Verify uvx works: `uvx --version` (re-run the installer to re-provision uv/python if not).","Check the captured subprocess output tail in logs for the crash reason.","Let the backoff reconnect run; if it never reconnects, restart the worker.","Free memory if an OOM kill is suspected."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import { spawnSync } from 'node:child_process';\n\nconst uvxOk = spawnSync('uvx', ['--version'], { encoding: 'utf8' }).status === 0;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep uv/uvx installed and on PATH.","Ensure enough memory for the Python chroma-mcp subprocess.","Update claude-mem regularly so the pinned chroma-mcp stays compatible."],"tags":["chroma","mcp","subprocess","reconnect","backoff"],"backgroundTag":"subprocess-crash-reconnect","analyzedSha":"8bc631a71a487424b866756e43a6efa4574cc66b","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}