Repository navigation
Stale rendezvous directory (/tmp/cbm-daemon-<uid>) permanently blocks install/update with "active CBM sessions ... could not be stopped safely" after hard-killed CBM processes #1760
Description
Version
codebase-memory-mcp 0.10.8
Platform
macOS (Apple Silicon)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
Title
Stale rendezvous directory (/tmp/cbm-daemon-<uid>) permanently blocks install/update with "active CBM sessions ... could not be stopped safely" after hard-killed CBM processes
Summary
After several long-lived codebase-memory-mcp MCP server processes were terminated non-gracefully (pkill, no clean shutdown), every subsequent codebase-memory-mcp install and codebase-memory-mcp update call failed permanently with:
Stopping active CBM sessions and operations for install...
error: active CBM sessions and operations could not be stopped safely; no activation was committed.
error: something is still using CBM. If an editor or agent is running an MCP server, close it and retry; 'codebase-memory-mcp daemon status' lists the holders when a cbm binary is still installed.
This happened even though every process-level and file-lock check came back completely clean:
ps aux | grep codebase-memory-mcp→ no matchescodebase-memory-mcp daemon status→daemon: not runninglsof +D ~/.cache/codebase-memory-mcp→ no open handles- No
*.lock,*.pid, or*.sockfiles under~/.cache/codebase-memory-mcp - No matching
launchctl listentries / no LaunchAgent plist - No stray files under
$TMPDIR(the per-user/var/folders/.../T/directory)
The installer's own diagnostics (daemon status, the error message itself) only ever point at "an editor or agent running an MCP server" — i.e. a process-level explanation — which sent us down the wrong debugging path for a long time. The actual blocker is stale on-disk coordination state, not a live process.
Environment
- OS: macOS (Apple Silicon / arm64)
- Shell: zsh
- Install method: official
install.sh(curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash), binary at~/.local/bin/codebase-memory-mcp - Affected versions: reproduced going from 0.10.1 → 0.10.8, and again fresh on 0.10.8 → 0.10.8 (re-running install to repair a corrupted agent config, see "related issue" below)
- ~25 indexed repositories, several coding-agent integrations detected (Claude Code, Codex CLI, VS Code, Junie, OpenHands, GitLab Duo CLI)
Suggested fixes
- Self-heal stale/unverified version-cohort claims. If a claim in
cbm-version-cohort-*-v1.lockhas no live process associated with it (e.g. viaflock/holder-PID liveness check), it should be treated as abandoned and cleared automatically, rather than blocking indefinitely. - Improve the error message to name the actual rendezvous directory and file(s) it's stuck on (similar to what v0.10.5's release notes describe doing for the Windows "directory that actually refused" case), instead of only suggesting "an editor or agent is running an MCP server."
- Document the rendezvous directory and
CBM_RUNTIME_DIRindocs/CONFIGURATION.md— currentlyCBM_RUNTIME_DIRis only mentioned in one release's changelog. - Provide a supported reset command, e.g.
codebase-memory-mcp daemon reset-coordinationor similar, instead of requiring users to manually locate andrm -rfan undocumented/tmpdirectory. - Consider whether
daemon status(which correctly reported "not running") should also inspect this rendezvous directory and warn about orphaned/unverified cohort claims even when no daemon process exists.
Workaround (for anyone hitting this)
# 1. Make sure nothing is actually running:
ps aux | grep -i codebase-memory-mcp
codebase-memory-mcp daemon status
# 2. If truly nothing is running but install/update still fails with
# "active CBM sessions and operations could not be stopped safely":
rm -rf /tmp/cbm-daemon-$(id -u)
# 3. Retry:
codebase-memory-mcp installRelated
- Installer/updater scope and safety: no per-client selector, destructive update step before an interactive prompt, hidden ui_enabled, brittle legacy-marker cleanup #1558 covers a different but adjacent installer-robustness gap in the same
install/updatepipeline (brittle legacy hook-marker cleanup causingagent_config ... op=legacy_hook_cleanup/ambiguous_hook_ownershipfailures on Codex CLI'sconfig.toml). We hit that one too, in the same troubleshooting session, right before hitting this one — the two are independent bugs but both erode trust ininstall/updatebeing safe to just "run again."
Reproduction
Steps to reproduce
- Have several coding-agent sessions running that each spawn their own
codebase-memory-mcpMCP server subprocess over stdio (no shared daemon —daemon statusreports "not running" the whole time). - Let those parent editor/agent windows terminate abnormally (in our case, likely closed without the MCP child process being reaped — we found 15 orphaned
codebase-memory-mcpprocesses, several days old, each with hundreds of CPU-minutes accumulated). - Terminate them non-gracefully:
pkill -f "/Users/<user>/.local/bin/codebase-memory-mcp" - Run
codebase-memory-mcp install(orupdate). It fails with the error above. - Confirm there is genuinely nothing left holding CBM open (steps listed in the Summary). The error persists indefinitely regardless.
Root cause (found via fs_usage)
Since neither the CLI's own diagnostics nor CBM_DIAGNOSTICS=true / CBM_LOG_LEVEL=debug surfaced the actual path being checked (the process exits before the periodic diagnostics writer ever runs), we traced the failing install invocation with:
sudo fs_usage -w -f filesys codebase-memory-mcp
This revealed a per-UID rendezvous/coordination directory that is not documented anywhere in docs/CONFIGURATION.md and is separate from ~/.cache/codebase-memory-mcp:
/private/tmp/cbm-daemon-<uid>/
containing (anonymized, real trace excerpt, timestamps/PID trimmed):
srw------- cbm-<hash>.anc
-rw------- cbm-<hash>.lifetime.lock
-rw------- cbm-<hash>.lock
srw------- cbm-<hash>.sock
-rw------- cbm-<hash>.startup-v2.lock
-rw------- cbm-version-cohort-admission-v1.lock
-rw------- cbm-version-cohort-daemon-v1.lock
-rw------- cbm-version-cohort-lifetime-v1.lock (214 bytes — the only non-empty file)
-rw------- cbm-version-cohort-maintenance-v1.lock
and, matching this, CBM_LOG_LEVEL=debug on a plain codebase-memory-mcp cli ... invocation (no install) printed:
level=info msg=version_cohort.claimed_unheld build=<sha>
codebase-memory-mcp: CBM CLI could not start because a pre-coordination or unverified CBM generation is active; close all CBM sessions and commands, then retry
Our reading: each CBM process "claims" a version-cohort slot in this directory for its generation/build, and expects a follow-up step to mark that claim as "held"/verified. When a process is killed abruptly (SIGKILL/hard pkill, or a crash — we also found a stale ~/Library/Application Support/CrashReporter/codebase-memory-mcp_*.plist), that follow-up never runs, and the claim is left dangling in cbm-version-cohort-lifetime-v1.lock / cbm-version-cohort-admission-v1.lock forever. Every later install/update/cli invocation sees an "unheld"/unverified claim and refuses to proceed, because from its perspective it cannot prove no other generation is mid-transition — even though, in reality, nothing is running anymore and the claim is simply orphaned.
Confirmed as the actual cause: removing the directory entirely resolved the issue immediately and permanently.
rm -rf /tmp/cbm-daemon-<uid>
codebase-memory-mcp install # now succeeds
We also found that CBM_RUNTIME_DIR (mentioned only in the v0.10.5 release notes, not in docs/CONFIGURATION.md) can point this coordination logic at a fresh directory as a workaround without touching the default one — useful for anyone who wants to unblock install without deleting the existing rendezvous directory outright:
CBM_RUNTIME_DIR=/tmp/cbm-runtime-clean codebase-memory-mcp install
Note, though, that this creates a split-brain: install then commits its "verified generation" state under the custom CBM_RUNTIME_DIR, while any later plain invocation (cli, an editor's MCP server launch, etc.) that does not set CBM_RUNTIME_DIR falls back to the still-broken default directory and immediately hits the same version_cohort.claimed_unheld / "pre-coordination or unverified CBM generation is active" error. CBM_RUNTIME_DIR is only a safe workaround if set consistently everywhere, or as a stepping stone before clearing and returning to the default directory (which is what ultimately fixed it for us).
Why this was hard to diagnose
The error message and daemon status hint entirely at live processes ("something is still using CBM... an editor or agent is running an MCP server... daemon status lists the holders"). There is no mention that:
- a per-UID directory under
/tmpholds durable cross-run coordination state independent of any running process, - that state can be inspected or reset via any documented command,
CBM_RUNTIME_DIRexists and affects this exact code path.
This sent us through a long, unproductive diagnostic chain (checking ps, lsof, launchctl, SQLite WAL files, license/session theories, etc.) before fs_usage tracing revealed the real location.
Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
No response
Confirmations
- I searched existing issues and this is not a duplicate.
- My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.
Activity
LinRds commentedon Aug 27, 2026
Hit this on 0.10.8, macOS 15 (Apple Silicon) running
install.shfrom~/.local/bin. Same failure text, and the event log shows the refusal happens with zero active clients, which may be the useful part.What the installer printed
Download and checksum both succeeded; the candidate verified as the same version already installed. Then:
Exit code was 0 despite
no activation was committed, so a scripted/CI update would record this as success while silently keeping the old binary.activation-events.ndjsonToday's failed run (fields trimmed):
{"phase":"requested","action":"install","daemon_active_clients":0,"daemon_active_connections":0,...} {"phase":"failed","action":"install","daemon_active_clients":0,"daemon_active_connections":0, "detail":"cohort drain or coordination failed"}For contrast, the successful install of the same version on this machine 8 days earlier:
{"phase":"daemon_stopped","action":"install","detail":"no active cohort"} {"phase":"completed","action":"install","detail":"activation mutation completed; ..."}So the drain fails while the installer itself observes
daemon_active_clients: 0anddaemon_active_connections: 0.Contradictory user-facing signals
The error message points at
daemon statusto list the holders, but at that moment:No processes existed either (
psshowed zerocodebase-memory-mcp). Following the error's own advice therefore dead-ends — there is no way to discover that/tmp/cbm-daemon-<uid>is the blocker.Same root cause as the daemon-side failure
On this machine the stale rendezvous directory was simultaneously blocking
daemon startwithCBM daemon could not start within 30000 ms(details in #1757 — markerless hard-linked.sock/.ancpair, no.identity/.pending). Onerm -rf /tmp/cbm-daemon-501cleared both failures at once: the daemon started on the next attempt, and install/update work again.Suggestions, in rough order of usefulness:
/tmp/cbm-daemon-<uid>— rather than pointing atdaemon status, which reportsnot runningin exactly this state.no activation was committed.ECONNREFUSED(this is what PR fix(cli): recover stale rendezvous publication before declaring BUSY (#1760) #1790 appears to be reaching for).fix: recover markerless stale rendezvous sockets during activation
gitokato commentedon Aug 31, 2026
Environment:
codebase-memory-mcp 0.10.8(build2412e017…), macOS (Apple Silicon), install.sh,binary at
~/.local/bin,uivariant. Daemon was watching 4 projects with auto-index/watch on.Different symptom: the runtime guard was completely blocked, not just install/update.
The same stale rendezvous state made every runtime entry point fail with the message:
This blocked all of: the MCP server connection (editor saw
CONNECTION_CLOSED),codebase-memory-mcp cli <tool>, plaincodebase-memory-mcp config list, and the daemon's ownbackground index workers. Same as here, every process/lock check was clean (
pgrep= 0 CBMprocesses; a fresh single-shot
config listwith no daemon alive still failed).The stuck artifacts were the
cbm-version-cohort-*-v1.lockfamily in/tmp/cbm-daemon-<uid>/(
…lifetime-v1.lockheld 214 bytes of state), consistent with a stuck pre-coordination /unverified generation claim — which may be a different artifact than the
.sock/.ancpair thatPR #1894 targets. Worth checking whether #1894's activation-path recovery also clears a stuck
version-cohort / unverified-generation claim that blocks the runtime guard, or only the install/update
path.
Concrete trigger (captured in
cbm-daemon.log)The daemon log shows the exact pivot into the wedged state. Workers reap cleanly until one is
killed mid-generation, and it never recovers after that:
So: a worker killed mid-index left the generation reservation unreleased, and the pre-coordination
guard then refused every subsequent start. Each failing worker log is identical:
Amplification: infinite auto-index retry loop
With auto-index/watch enabled, the file watcher re-fired the index on every
watcher.changedfora dirty git tree, so the failing worker spawned continuously — ~230 identical failing worker logs
accumulated and one process sat pinned in
Rstate at high CPU for days. A stuck reservation plusauto-index turns a one-time crash into a hot loop.
Happy to grab a
CBM_DIAGNOSTICS=1trajectory or theactivation-events.ndjsonif useful — this wason a live wedge that's since been cleared, but it's reproducible by killing a worker mid-generation.
Tomauskasz commentedon Sep 7, 2026
Hit this independently today (2026-09-07) on 0.10.8, same symptoms and same root cause.
One more data point: with the rendezvous dir in this stuck state,
codebase-memory-mcp daemon startalso fails outright — it times out withCBM daemon could not start within 30000 msafter only printingversion_cohort.claimed_unheldto stderr. It never got far enough to write anything to~/.cache/codebase-memory-mcp/logs/cbm-daemon.log, even with zero live clients and zero daemon processes running. So this isn't limited toinstall/update/cli— it blocks daemon startup entirely too.Confirmed the same fix:
rm -rf /tmp/cbm-daemon-$(id -u)resolved it immediately —daemon startandconfig get/setall worked right after, no reinstall needed.DeusData commentedon Sep 7, 2026
Fixed on main by 760c08f (PR #1894, thank you @mvanhorn, and thanks to everyone who confirmed the shape here): a hard-killed daemon or worker no longer leaves a markerless .sock/.anc pair plus an unheld cohort lock that wedges install, update and every CLI or MCP entry point behind the 30 s "active or starting" timeout; activation now runs the serialized stale-generation cleanup before classifying. Ships in v0.10.9. If you still hit it on that release, please say so here with
daemon statusand the contents of /tmp/cbm-daemon-.fix: recover markerless stale rendezvous sockets during activation