Before submitting
π Manual Bug Report
Bug Description
When CLAUDE_MEM_CHROMA_ENABLED=true (default), zombie uv +
python3.13 process pairs accumulate over time until the system has
hundreds of processes consuming several GB of memory. Observed: 600+
python processes consuming ~6.5 GB of RAM, requiring a manual
kill-all to recover.
Steps to Reproduce
- Enable CLAUDE_MEM_CHROMA_ENABLED=true (this is the default)
- Open 3β5 Claude Code sessions simultaneously across different
projects
- Use Claude actively for several hours (generating
observations/syncs)
- Run ps aux | grep python3 | grep -v grep | wc -l
The process count grows proportionally to: session count Γ sync
frequency Γ kill failure rate.
Expected Behavior
Old subprocess should be fully terminated before spawning a new one.
If killProcessTree fails, it should retry or use process group kill
(kill -pgid) instead of silently swallowing the error.
Root Cause Analysis
Three issues combine to produce this:
- killProcessTree is best-effort and silently swallowed
In worker-service.cjs, when chroma-mcp closes unexpectedly:
t.killProcessTree(u).catch(d => {
v.debug("CHROMA_MCP", "Background tree-kill after onclose finished
(best-effort)", ...)
// error is silently ignored β old process keeps running
})
On macOS, kill -9 on the uv parent does not reliably kill the
python3.13 child. The child becomes an orphan. Since the error is
swallowed, there is no retry or fallback.
- Short-connection pattern β no connection reuse
Every chroma sync spawns a new uvx --python 3.13 chroma-mcp
subprocess, connects, uses it, then closes. Connections are never
reused. This results in 30+ connect/disconnect cycles over a few
hours of active use.
- Concurrent sessions cause lock contention β timeout β reconnect
loop
Multiple Claude Code sessions each try to connect to the same chroma
persistent data dir simultaneously. The file lock causes connection
attempts to hang past the 30s timeout, each leaving an un-killed uv
- python3.13 pair. The next retry spawns a new pair on top of the
orphaned ones.
Suggested Fixes
- Use process group kill on macOS/Linux instead of single-PID kill:
process.kill(-pgid, 'SIGKILL') // kills entire process group
- Reuse the chroma-mcp connection across sync operations instead of
spawn-per-sync
- Add a concurrency lock so only one worker connects to the local
chroma data dir at a time
- Verify kill success before spawning a new subprocess
Environment
- Claude-mem version: 13.4.2
- Claude Code version: 2.1.169
- OS: macOS 26.5.1
- Platform: arm64
Logs
[WARN ] [CHROMA_MCP] Connection failed, killing subprocess tree to
prevent zombie {error=MCP connection to chroma-mcp timed out after
30000ms}
[ERROR] [CHROMA_MCP] Connection attempt failed MCP connection to
chroma-mcp timed out after 30000ms
[ERROR] [CHROMA_SYNC] Backfill failed for project: MCP
connection to chroma-mcp timed out after 30000ms
[WARN ] [CHROMA_MCP] chroma-mcp subprocess closed unexpectedly,
applying reconnect backoff
The timeout pattern repeated 4 times in a single day (roughly every
1β4 hours of active use), and the unexpected-close event occurred
once additionally.
Additional Context
Workaround: Set CLAUDE_MEM_CHROMA_ENABLED=false in
~/.claude-mem/settings.json. This disables semantic search but
eliminates the leak entirely.
The uvx command used to spawn chroma-mcp:
uvx --python 3.13 --with onnxruntime>=1.20 --with protobuf<7
chroma-mcp==0.2.6 --client-type persistent
Before submitting
duplicate
π Manual Bug Report
Bug Description
When CLAUDE_MEM_CHROMA_ENABLED=true (default), zombie uv +
python3.13 process pairs accumulate over time until the system has
hundreds of processes consuming several GB of memory. Observed: 600+
python processes consuming ~6.5 GB of RAM, requiring a manual
kill-all to recover.
Steps to Reproduce
projects
observations/syncs)
The process count grows proportionally to: session count Γ sync
frequency Γ kill failure rate.
Expected Behavior
Old subprocess should be fully terminated before spawning a new one.
If killProcessTree fails, it should retry or use process group kill
(kill -pgid) instead of silently swallowing the error.
Root Cause Analysis
Three issues combine to produce this:
In worker-service.cjs, when chroma-mcp closes unexpectedly:
On macOS, kill -9 on the uv parent does not reliably kill the
python3.13 child. The child becomes an orphan. Since the error is
swallowed, there is no retry or fallback.
Every chroma sync spawns a new uvx --python 3.13 chroma-mcp
subprocess, connects, uses it, then closes. Connections are never
reused. This results in 30+ connect/disconnect cycles over a few
hours of active use.
loop
Multiple Claude Code sessions each try to connect to the same chroma
persistent data dir simultaneously. The file lock causes connection
attempts to hang past the 30s timeout, each leaving an un-killed uv
orphaned ones.
Suggested Fixes
process.kill(-pgid, 'SIGKILL') // kills entire process group
spawn-per-sync
chroma data dir at a time
Environment
Logs
[WARN ] [CHROMA_MCP] Connection failed, killing subprocess tree to
prevent zombie {error=MCP connection to chroma-mcp timed out after
30000ms}
[ERROR] [CHROMA_MCP] Connection attempt failed MCP connection to
chroma-mcp timed out after 30000ms
[ERROR] [CHROMA_SYNC] Backfill failed for project: MCP
connection to chroma-mcp timed out after 30000ms
[WARN ] [CHROMA_MCP] chroma-mcp subprocess closed unexpectedly,
applying reconnect backoff
The timeout pattern repeated 4 times in a single day (roughly every
1β4 hours of active use), and the unexpected-close event occurred
once additionally.
Additional Context
Workaround: Set CLAUDE_MEM_CHROMA_ENABLED=false in
~/.claude-mem/settings.json. This disables semantic search but
eliminates the leak entirely.
The uvx command used to spawn chroma-mcp:
uvx --python 3.13 --with onnxruntime>=1.20 --with protobuf<7
chroma-mcp==0.2.6 --client-type persistent