thedotmack/claude-mem · warning

Transport error during "${toolName}", reconnecting and retry

Error message

Transport error during "${toolName}", reconnecting and retrying once

What it means

A chroma MCP tool call failed with a transport-level error (subprocess crash, closed stdio pipe, dropped session). The manager tree-kills the dying subprocess (preventing Linux descendant leaks, #2313), reconnects, and retries the exact call once. A single warn is expected noise; if the retry also fails, that error propagates to the caller.

Source

Thrown at src/services/sync/ChromaMcpManager.ts:780

    return this.enqueueMutation(() => this.callToolUnqueued(toolName, toolArguments), toolName);
  }

  private async callToolUnqueued(toolName: string, toolArguments: Record<string, unknown>): Promise<unknown> {
    const callGeneration = this.connectionGeneration;
    await this.ensureConnected();

    logger.debug('CHROMA_MCP', `Calling tool: ${toolName}`, {
      arguments: JSON.stringify(toolArguments).slice(0, 200)
    });

    let result;
    try {
      result = await this.client!.callTool({
        name: toolName,
        arguments: toolArguments
      });
    } catch (transportError) {
      logger.warn('CHROMA_MCP', `Transport error during "${toolName}", reconnecting and retrying once`, {
        error: transportError instanceof Error ? transportError.message : String(transportError)
      });

      if (callGeneration !== this.connectionGeneration) {
        throw new ChromaMcpConnectionCancelledError('chroma-mcp call cancelled during shutdown');
      }

      // Tree-kill the dying subprocess before reconnect. Previously this path
      // just nulled the handle, which on Linux leaks the uv/python/chroma-mcp
      // descendants every time a transport error happens (#2313).
      await this.disposeCurrentSubprocess();

      try {
        if (callGeneration !== this.connectionGeneration) {
          throw new ChromaMcpConnectionCancelledError('chroma-mcp call cancelled during shutdown');
        }
        await this.ensureConnected();
        result = await this.client!.callTool({

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Treat isolated occurrences as benign — the built-in reconnect-and-retry usually recovers
  2. If recurrent, check dmesg or journalctl for OOM kills of the uv/python children
  3. Keep claude-mem and chroma-mcp versions matched so protocol versions agree
  4. Correlate with connect-time stderrTail warnings to find the underlying crash
Defensive patterns

Strategy: retry

Type guard

import { ChromaMcpConnectionCancelledError } from './errors';

function isConnectionCancelled(e: unknown): boolean {
  return e instanceof ChromaMcpConnectionCancelledError;
}

Try / catch

try {
  result = await manager.callTool(toolName, args);
} catch (err) {
  if (isConnectionCancelled(err)) throw err; // shutdown in progress — do not retry
  // one internal reconnect+retry already happened; treat final failure as degraded
  enterDegradedMode();
}

Prevention

When it happens

Trigger: callTool() in flight when the chroma-mcp process dies — OOM kill, chroma crash, native crash — or the stdio pipe breaking during suspend/resume or protocol version mismatch causing a hard close.

Common situations: chroma-mcp children killed by an OS OOM manager; laptops sleeping mid-call; client/server MCP protocol drift after partial upgrades.

Related errors


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20). Data as JSON: /api/errors/70f9bc139d168a1b. Report an issue: GitHub.