{"record":{"id":"94f8e5b541e6bbfa","repo":"thedotmack/claude-mem","slug":"chroma-mcp-transport-error-during-toolname-r","errorCode":null,"errorMessage":"chroma-mcp transport error during \"${toolName}\" (retry failed): ${retryError instanceof Error ? retryError.message : String(retryError)}","messagePattern":"chroma-mcp transport error during \"(.+?)\" \\(retry failed\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/sync/ChromaMcpManager.ts","lineNumber":850,"sourceCode":"      }\n\n      // Tree-kill the dying subprocess before reconnect. Previously this path\n      // just nulled the handle, which on Linux leaks the uv/python/chroma-mcp\n      // descendants every time a transport error happens (#2313).\n      await this.disposeCurrentSubprocess();\n\n      try {\n        if (callGeneration !== this.connectionGeneration) {\n          throw new ChromaMcpConnectionCancelledError('chroma-mcp call cancelled during shutdown');\n        }\n        await this.ensureConnected();\n        result = await this.client!.callTool({\n          name: toolName,\n          arguments: toolArguments\n        });\n      } catch (retryError) {\n        this.connected = false;\n        throw new Error(`chroma-mcp transport error during \"${toolName}\" (retry failed): ${retryError instanceof Error ? retryError.message : String(retryError)}`);\n      }\n    }\n\n    if (result.isError) {\n      const errorText = (result.content as Array<{ type: string; text?: string }>)\n        ?.find(item => item.type === 'text')?.text || 'Unknown chroma-mcp error';\n      throw new Error(`chroma-mcp tool \"${toolName}\" returned error: ${errorText}`);\n    }\n\n    const contentArray = result.content as Array<{ type: string; text?: string }>;\n    if (!contentArray || contentArray.length === 0) {\n      return null;\n    }\n\n    const firstTextContent = contentArray.find(item => item.type === 'text' && item.text);\n    if (!firstTextContent || !firstTextContent.text) {\n      return null;\n    }","sourceCodeStart":832,"sourceCodeEnd":868,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/sync/ChromaMcpManager.ts#L832-L868","documentation":"Generic Error thrown when the single reconnect-and-retry for a failed chroma-mcp tool call also fails. The first attempt hit a transport error, the manager disposed the subprocess and reconnected, but the retry (ensureConnected or the second callTool) threw; the manager marks itself disconnected and wraps the retry failure in a descriptive transport error naming the tool and original failure.","triggerScenarios":"client.callTool() throws a transport error (subprocess died, stdio stream broken), and after disposeCurrentSubprocess + ensureConnected the retried callTool or reconnection throws again — e.g. uvx cannot respawn chroma-mcp, port/resource unavailable, or the child crashes immediately.","commonSituations":"Missing or broken uv/uvx installation so chroma-mcp cannot be relaunched; chroma-mcp version incompatibility causing instant crash; system resource exhaustion (OOM, fd limits); network/stdio corruption under load.","solutions":["Inspect the wrapped retryError message to find the root cause of the retry failure.","Verify uv/uvx is installed and can launch chroma-mcp (run the uvx command manually with the same args).","Pin/upgrade the chroma-mcp package version; an incompatible update often causes immediate subprocess crashes.","Check system resources (memory, file descriptors) that could kill the respawned subprocess.","Catch this error, wait, and retry with backoff — the manager sets connected=false so the next call triggers a fresh reconnect.","If shutdown was in progress, the underlying cause may be a cancellation surfaced here; treat accordingly."],"exampleFix":"// before\nconst result = await manager.callTool('chroma_query_documents', args); // throws on transient subprocess crash\n// after\nlet result;\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    result = await manager.callTool('chroma_query_documents', args);\n    break;\n  } catch (e) {\n    if (String(e.message).includes('transport error') && attempt < 2) {\n      await new Promise(r => setTimeout(r, 500 * 2 ** attempt));\n      continue;\n    }\n    throw e;\n  }\n}","handlingStrategy":"retry","validationCode":"// Pre-flight: confirm uvx can launch chroma-mcp before issuing calls\nconst { execFileSync } = require('child_process');\ntry { execFileSync('uvx', ['--version'], { stdio: 'ignore' }); }\ncatch { throw new Error('uv/uvx unavailable; chroma-mcp cannot be respawned'); }","typeGuard":"function isTransportRetryFailure(e: unknown): boolean {\n  return e instanceof Error && e.message.includes('transport error') && e.message.includes('retry failed');\n}","tryCatchPattern":"try {\n  result = await manager.callTool(toolName, args);\n} catch (e) {\n  if (/transport error .*\\(retry failed\\)/.test((e as Error)?.message ?? '')) {\n    await sleep(backoffMs);\n    result = await manager.callTool(toolName, args); // next call triggers fresh reconnect\n  } else { throw e; }\n}","preventionTips":["Install and keep uv/uvx on PATH so the subprocess can be respawned","Pin a compatible chroma-mcp version; verify it launches manually with the same args","Monitor memory/fd limits that can kill the respawned child","Retry with exponential backoff since the manager marks itself disconnected","Check the inner retryError message for the true root cause"],"tags":["chroma","mcp","transport","subprocess","retry"],"backgroundTag":"connection-refused","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"}