Repository navigation
Description
v0.6.0 (confirm via codebase-memory-mcp --version before filing), Windows 11, stdio MCP registration via project-scope .mcp.json.
Relationship to existing CLOSED issues
Triaged before filing; distinct from all three:
- Multiple instances of codebase-memory-mcp.exe running and 2 databases in the same project. #50 (CLOSED, v0.4.8 + v0.5.0 C-rewrite fixed it): duplicate DBs from drive-letter casing. Ours is NOT duplicate DBs — one
.dbfile per project, the right one, but its mtime is frozen while its.db-walaccumulates writes. - Server hangs and requires SIGKILL after list_projects on large project (SQLite lock contention) #52 (CLOSED):
list_projectshang + stuckdb-shmfrom SIGKILL-mid-transaction. Substrate overlap (WAL+shm stuck states), different manifestation: our server does NOT hang; it responds normally; it just returns stale data for symbols that exist in the WAL but have never been checkpointed into the main.db. - fix(mcp): query handlers silently return empty results for unindexed projects; resolve_store creates ghost .db files #119 (CLOSED, PR fix(mcp,store): guard query handlers against unindexed projects; prevent ghost .db files #120 ~2026-03-23): query handlers silently return empty for unknown/unindexed projects + ghost-
.dbcreation. Our project IS indexed (index_repositoryreturnsstatus: indexed, nodes: N, edges: Mwith N/M > 0 for the project's pre-existing symbols, andlist_projectslists it), but queries for symbols defined in files added POST-initial-index return empty. Adjacent bug class; fix(mcp): query handlers silently return empty results for unindexed projects; resolve_store creates ghost .db files #119's guard does not cover this.
If this repro turns out to be a re-emergence of any of the above under a new code path, please re-close as duplicate with a pointer.
Symptom
index_repository returns status: indexed, nodes: N, edges: M where (N, M) are the pre-add-new-file counts — the indexer reports success but the returned counts do not reflect the files added since the last clean checkpoint. search_graph, search_code, and trace_path all return empty for symbols in files added since. Affects both delete_project → index_repository rebuild AND incremental re-index cycles; i.e., even a full rebuild-from-scratch from the MCP-tool-surface does NOT resolve it.
Root cause (empirically verified)
Multiple stdio-spawned codebase-memory-mcp.exe processes persist across client session closes — 10 orphan processes observed in our case, accumulated across multiple Claude Code sessions where stdio shutdown did not handshake cleanly. SQLite WAL at ~/.cache/codebase-memory-mcp/<project>.db-wal grows (9.1 MB observed) while the main <project>.db file's mtime stays frozen at the date of the last clean checkpoint. New symbols get written to WAL, but checkpoint-into-main cannot land because orphan-process connections hold read locks.
Verified by: after running taskkill /F /IM codebase-memory-mcp.exe on all 10 processes + rm ~/.cache/codebase-memory-mcp/<project>.db* (all three files: .db, .db-shm, .db-wal) + re-indexing the project, we observed a +42 node / +41 edge delta for that project — multiple prior sessions' accumulated index writes finally landed. delete_project + index_repository cycle alone does NOT resolve this; the orphan-process kill + cache-file delete is required.
Minimal repro (Windows)
- Index a project via
index_repository, confirm symbols appear insearch_graph. - Close the client session without a clean stdio-shutdown handshake (typical — stdio parent-death is SIGHUP-equivalent, not a graceful close).
- Open a new client session against the same project.
- Add a new
.pyfile with a distinct function name. delete_project→index_repository→search_graph(name_pattern=".*new_fn.*")→total: 0.ls -la ~/.cache/codebase-memory-mcp/shows.db-walgrowing across retries;.dbmtime stuck at first-ever-index date.tasklist | findstr codebase-memory-mcpshows N > 1 orphan processes.
Workaround
taskkill //F //IM codebase-memory-mcp.exe
rm ~/.cache/codebase-memory-mcp/<project>.db*
# — next client tool call auto-respawns a fresh server via stdio
# (no manual restart needed if registered via .mcp.json)
Verified working; the client-side MCP auto-respawn is transparent. Other projects' indexes in the cache are preserved (they have separate .db files per project).
Proposed fixes
- On
delete_project: issuePRAGMA wal_checkpoint(TRUNCATE)before touching files on disk. - On startup: detect stale
.db-walbeyond a threshold (10 MB?) and either force-checkpoint or emit a loud warning. - On stdio-close: trap SIGTERM / stdio EOF and run
PRAGMA wal_checkpoint(TRUNCATE)before exit. - Document the orphan-process failure mode in the README's troubleshooting section.
Downstream context
Encountered while building Outside-Diff Impact Slicing (ODSC) review agents that depend on this MCP's trace_path + detect_changes. Our diagnostic trail is at
.claude/agents/VALIDATION_LOG.md Entry 2 (§"Cold-start resolution (2026-04-21, same session)") of the downstream project; see
https://github.com/davidseraphi/PROJECT_MEMORY_ENGINE_OS/blob/master/.claude/agents/VALIDATION_LOG.md
(public once the current local-ahead commits are pushed — available on request if not yet visible when this issue is triaged).
Happy to run additional diagnostics on our repro on request (e.g., sqlite3 <db> 'PRAGMA wal_checkpoint;' against the stuck-state DB to confirm the checkpoint-cannot-land hypothesis mechanically).
Activity
LWarrens commentedon Apr 22, 2026
If you're open to using a proxy HTTP server, there's a pretty solid general fix you can apply.
(I chose a node mcp proxy)
Install NodeJS and the mcp-proxy package
Next, choose a port (for example, 9999) and start the proxy which will start a single instance of codebase-memory-mcp :
fracampit commentedon May 24, 2026
Confirming this reproduces on v0.6.1, Windows 11. A different trigger path adds evidence to the orphan-process WAL-lock root cause you've identified, and on Windows the same lock additionally manifests as a hard
delete_project"Permission denied" error — relevant for the proposed fixes list.Same root cause, different trigger
In our case the stale-graph trigger was upstream code landing via git merge between MCP sessions, not new files added in the current session.
index_repository(mode="full")expecting the new symbols to land.status: indexedwith the pre-merge node/edge counts unchanged. No error, no warning.search_graphfor the new symbol names all returned 0 results.So the bug surface is broader than "files added since last index in the same session" — any new files in the working tree at the time of a re-index are silently dropped if the WAL-checkpoint can't land. Merging an upstream PR is a common path to this state for anyone running a long-lived MCP setup with async PR flow.
Windows manifestation:
delete_projectreturns "Permission denied"When attempting the natural recovery path before discovering your
taskkill+ manual delete workaround, both forms ofdelete_projectreturned a hard error rather than silently succeeding:This is consistent with your root-cause analysis: orphan
codebase-memory-mcp.exeprocesses (3 in our case, visible viaGet-Process -Name codebase-memory-mcp) held open handles on<project>.db+.db-wal+.db-shm. On Windows,unlink()against a file with an open handle that was opened withoutFILE_SHARE_DELETEreturnsERROR_SHARING_VIOLATION, surfaced to the caller asPermission denied. Sodelete_project's file-deletion path hits the same lock that's blocking the WAL checkpoint — but instead of silently no-op-ing the wayindex_repositorydoes, it fails loudly.Relevant to your proposed fix list:
On Windows this likely won't be sufficient on its own — the checkpoint itself will fail because the orphan processes still hold the read locks. The full fix probably needs one of:
FILE_SHARE_DELETE(SQLITE_OPEN_DELETEONCLOSE-adjacent semantics) from the start sounlinksucceeds even with concurrent readers, orcbm cleanup/cbm resetsubcommand that does thetaskkill+ delete dance reliably and document it in the troubleshooting section.Workaround confirmed
The exact workaround from your issue body resolves it on Windows too:
After kill + delete + fresh re-index from a new Claude Code session, the post-PR symbols landed correctly. The kill-delete-reindex cycle is now part of our documented per-repo workflow until upstream resolves the WAL release.
Happy to test candidate fixes against this repro if a PR lands.
fracampit commentedon May 24, 2026
Follow-up correction to my earlier comment — same-day empirical retest narrows the bug surface, and I want to update the record so the maintainer's triage isn't biased by my overstatement.
What I overstated
My earlier comment described a "different trigger" — "upstream code landing via git merge between MCP sessions" — implying the bug surface is broader than the original repro in this issue. That framing was wrong. Same-day retest with only one Claude Code session open (single
codebase-memory-mcp.exeprocess, no orphans) refuted the "silent no-op" symptom entirely:Killed all
codebase-memory-mcp.exeprocesses, deleted the project's.db*files, rancodebase-memory-mcp cli index_repository '{"repo_path":"..."}'— fresh graph built cleanly (10,858 nodes / 15,927 edges on a 1323-file TS monorepo).Immediately re-indexed (no code changes between calls):
Returned the same counts. Honest, explicit noop logging — not silent.
Re-indexed a second project (also previously indexed): same honest noop behavior.
Process count after all CLI work: still 1. No orphan accumulation.
Under single-session conditions, the tool's incremental hash-comparison is honest and the "silent no-op" symptom does not reproduce. The original bug in this issue is real — but its triggering condition is more specific than my earlier comment suggested.
What appears to actually trigger it
Multiple concurrent
codebase-memory-mcp.exeprocesses holding open SQLite handles on the same project's.db/.db-wal/.db-shmfiles. In my case, those processes came from multiple concurrent Claude Code sessions, each spawning its own stdio MCP server. The orphan-process scenario this issue's body describes is one path to that state (uncleanly-closed sessions accumulating); my "post-merge" framing was another path (merging code while multiple live sessions were holding locks); but the underlying mechanism is the same: lock contention preventing WAL checkpoints, not a structural bug inindex_repository.Implications for the proposed fix list in this issue
The fix proposals here are still right —
wal_checkpoint(TRUNCATE)ondelete_project, stale-WAL detection on startup, SIGTERM/EOF handler, README troubleshooting docs. The Windowsdelete_projectPermission denied manifestation I described still holds (open file handles →unlink()returnsERROR_SHARING_VIOLATION). What changes:The bug surface isn't "any session that's re-indexed after files landed"; it's "any session running while another process holds locks on the same DB." So the proposed README troubleshooting should call out "check for concurrent client sessions / orphan processes before invoking the recovery workflow" as the first diagnostic step, rather than framing the kill-delete-reindex as the default recovery.
A useful intermediate workaround that doesn't require any server-side change: the CLI mode (
codebase-memory-mcp cli <tool> '{...}') is one-shot per invocation — each call spawns a fresh process, opens its own SQLite handle, does the work, and exits cleanly. No persistent connection, no orphan accumulation. Works in parallel with a live MCP server in another session. For clients that need to re-index after significant code changes mid-conversation, CLI is the clean escape; for the MCP-transport-only path, the proposed fixes here still apply.Happy to test candidate PRs against this single-session-clean state for regression on the honest-noop logging, or against a deliberately-orphan-loaded state for the contention path.
fix(store): checkpoint WAL on close and startup to prevent orphan acc…
fix(store): checkpoint WAL on close and startup to prevent orphan acc…
fix(store): checkpoint WAL on close and startup to prevent orphan acc…
nwn900 commentedon Jun 19, 2026
I have the following issue too