Skip to content

Daemon start fails with daemon.ipc.listen_failed stage=pending_publication when /tmp is full; clients get a misleading "active or starting" 30s timeout and MCP hosts silently drop the server #1828

Description

@AlexMKX

Summary

On Linux the daemon's rendezvous directory lives in /tmp (/tmp/cbm-daemon-<uid>, cf. #1672, #1760). When /tmp is a tmpfs that fills up, the daemon cannot publish its listener and dies on every start attempt. The failure is reported to clients as "CBM daemon is active or starting but could not accept this client within 30000 ms" — which describes the opposite of what happened, names no cause, and names no path. MCP hosts simply drop the server, so an agent loses every graph tool with no signal that anything is wrong.

In our case this went unnoticed for ~10 hours on an unattended review bot.

Environment

  • codebase-memory-mcp 0.10.8 (official release binary, ~/.local/bin/codebase-memory-mcp)
  • Ubuntu, kernel 7.0.0-30-generic, headless CI-style host, user uid 1000
  • /tmp = tmpfs, 3.9G (default sizing), root filesystem 61G at 18% used
  • Host: MCP client is opencode, registering CBM as a type: local stdio server

Symptoms

Daemon log (~/.cache/codebase-memory-mcp/logs/cbm-daemon.log) — this triplet repeats on every single start attempt:

level=info  msg=mem.init budget_mb=1984 total_ram_mb=7936 source=ram_fraction
level=error msg=daemon.ipc.listen_failed stage=pending_publication
level=error msg=daemon.runtime.start_failed stage=listener_handoff
level=error msg=daemon.start_failed component=runtime

Every client fails identically. Plain CLI:

$ codebase-memory-mcp cli --json list_projects
error: CBM daemon is active or starting but could not accept this client within 30000 ms

MCP host side (opencode log):

WARN message="server unavailable" key=codebase-memory-mcp type=local status=failed

The agent's tool list then contains no codebase-memory-mcp_* tools at all. Asked directly, the agent answered: "Tools containing 'codebase': none." It had no way to distinguish "graph server is broken" from "this host has no graph server", so it silently fell back to reading files one at a time.

What we verified (to rule out the obvious)

  • Not stale local state. We moved the entire ~/.cache/codebase-memory-mcp aside and started from a completely fresh state — identical failure, byte for byte. (State was then restored.)
  • No socket-name collision. ss -xlp | grep -iE "cbm|codebase" was empty, and there were zero CBM processes running at the time.
  • It fails before it ever binds. strace -f -e trace=bind,socket,unlink,openat of --cbm-daemon-internal recorded no bind() call whatsoever — consistent with the failure being at stage=pending_publication, i.e. while creating the rendezvous artifacts, not while listening.
  • Not disk space in the usual sense. df -h / and /home showed 18% used with 51G free the whole time. Only /tmp — a separate 3.9G tmpfs — was exhausted. Anyone debugging this by checking df on the wrong mount point (as we did at first) is led away from the cause.
  • Not a version conflict. /usr/local/bin/codebase-memory-mcp is a symlink to the same 0.10.8 binary.

Root cause and the fix that worked

Enlarging the /tmp tmpfs from 3.9G to 12G restored operation immediately, with no reinstall, no cache change, and no restart of anything else. The daemon came up on the next client call and /tmp/cbm-daemon-1000 was repopulated:

drwx------ 2 ubuntu ubuntu 340 /tmp/cbm-daemon-1000
  cbm-<hash>.rw
  cbm-<hash>.turn
  cbm-<hash>.lifetime.lock

So: /tmp full → rendezvous publication fails → daemon start fails → all clients time out against a daemon that is not actually "starting".

Why this is worth fixing beyond the disk-space part

The disk being full is our problem. These three are not:

  1. The client error states the opposite of the truth. "active or starting" is emitted when the daemon has definitively failed to start — and the daemon knows it, because it logged daemon.start_failed three times before the client's 30s deadline expired. A client that waits 30 seconds to print a misleading sentence is worse than one that fails in 100 ms with the real reason.
  2. No errno, no path, anywhere. Neither daemon.ipc.listen_failed nor the client message names the syscall, the errno, or /tmp/cbm-daemon-<uid>. stage=pending_publication is only meaningful to someone who already knows the code. Surfacing ENOSPC and the target path would have turned a multi-hour investigation into a one-line diagnosis.
  3. The MCP host degrades silently. The host marks the server failed and moves on; the agent never learns that a capability it was told it has is missing. Whatever the transport-level right answer is, the practical effect today is an agent that quietly stops using the graph and produces worse work with no warning.

Suggested changes

Happy to run any diagnostic you'd like on the affected host; it is still available and the failure is reproducible by filling /tmp.

Metadata

Metadata

Assignees

No one assigned

    Labels

    editor/integrationEditor compatibility and CLI integrationstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions