thedotmack/claude-mem · info · ChromaMcpConnectionCancelledError
chroma-mcp call cancelled during shutdown
Error message
chroma-mcp call cancelled during shutdown
What it means
ChromaMcpConnectionCancelledError thrown when the first chroma-mcp client.callTool() attempt fails with a transport error AND the manager's connectionGeneration has changed in the meantime, meaning a reconnect/dispose (typically triggered by shutdown) invalidated this call. Rather than retrying a stale connection, the manager cancels the in-flight call so it does not race with the new connection lifecycle.
Solutions
- Catch ChromaMcpConnectionCancelledError and treat it as a cancellation, not a data error — retry the operation after the manager is reconnected or restarted.
- Check whether shutdown was expected; if the call must complete, ensure no concurrent dispose/reconnect runs while a tool call is in flight.
- Add a coordination layer that stops issuing callTool requests once shutdown begins.
- Update the chroma-mcp runtime (uvx/uv) if transport errors are frequent, indicating an unstable subprocess.
- Enable CHROMA_MCP debug logging to confirm the generation mismatch and identify what bumped connectionGeneration.
Example fix
// before
const result = await manager.callTool('chroma_query_documents', { query: q });
// after
try {
const result = await manager.callTool('chroma_query_documents', { query: q });
} catch (e) {
if (e instanceof ChromaMcpConnectionCancelledError) {
return null; // cancelled by shutdown; retry later
}
throw e;
} Defensive patterns
Strategy: try-catch
Type guard
function isCancelled(e: unknown): e is Error {
return e instanceof Error && e.message.includes('call cancelled during shutdown');
} Try / catch
try {
await manager.callTool('chroma_query_documents', args);
} catch (e) {
if (e instanceof ChromaMcpConnectionCancelledError) return null; // benign shutdown cancellation
throw e;
} Prevention
- Drain in-flight tool calls before shutting down the manager
- Do not call callTool concurrently with dispose/reconnect paths
- Log connectionGeneration changes to diagnose mid-call invalidation
- Retry the operation on a fresh manager instance if the result is required
When it happens
Trigger: client.callTool() throws a transport error while, concurrently, another code path bumps connectionGeneration (disposeCurrentSubprocess/reconnect during shutdown or connection reset). The generation check after the failed attempt detects the staleness and throws.
Common situations: chroma-mcp subprocess crashes (uvx/python dies, OOM kill) at the same moment the user quits the app; transport drop during shutdown triggers the reconnect path but the generation token has already moved.
Related errors
- chroma-mcp transport error during
- queued chroma-mcp mutation cancelled during shutdown
- Transport error during
- chroma-mcp connection cancelled during shutdown
- chroma-mcp connection failed
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/81fdee5f3b221aa5.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/sync/ChromaMcpManager.ts:831
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({
name: toolName,
arguments: toolArguments
});
} catch (retryError) {
this.connected = false;View on GitHub (pinned to d8bc9755e7)