Skip to content

New files not indexed — WAL-checkpoint blocked on successfully-indexed project (Windows, v0.6.0) #277

Closed

Description

@davidseraphi

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:

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)

  1. Index a project via index_repository, confirm symbols appear in search_graph.
  2. Close the client session without a clean stdio-shutdown handshake (typical — stdio parent-death is SIGHUP-equivalent, not a graceful close).
  3. Open a new client session against the same project.
  4. Add a new .py file with a distinct function name.
  5. delete_project → index_repository → search_graph(name_pattern=".*new_fn.*") → total: 0.
  6. ls -la ~/.cache/codebase-memory-mcp/ shows .db-wal growing across retries; .db mtime stuck at first-ever-index date.
  7. tasklist | findstr codebase-memory-mcp shows 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: issue PRAGMA wal_checkpoint(TRUNCATE) before touching files on disk.
  • On startup: detect stale .db-wal beyond 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

  1. LWarrens commented on Apr 22, 2026

    @LWarrens

    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

    npm -g install mcp-proxy

    Next, choose a port (for example, 9999) and start the proxy which will start a single instance of codebase-memory-mcp :

    mcp-proxy --port SOME_PORT --server stream -- codebase-memory-mcp
    "codebase-memory-mcp": {
        "type": "http",
        "url": "http://localhost:SOME_PORT/mcp"
    }
  2. added
    bugSomething isn't working
    windowsWindows-specific issues
    stability/performanceServer crashes, OOM, hangs, high CPU/memory
    on May 4, 2026
  3. fracampit commented on May 24, 2026

    @fracampit

    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.

    1. Indexed a private TypeScript monorepo (TS LSP-hybrid mode).
    2. A PR merged into the working branch, adding several new files (a few React components and a hook).
    3. Started a fresh Claude Code session, called index_repository(mode="full") expecting the new symbols to land.
    4. MCP returned status: indexed with the pre-merge node/edge counts unchanged. No error, no warning.
    5. search_graph for 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_project returns "Permission denied"

    When attempting the natural recovery path before discovering your taskkill + manual delete workaround, both forms of delete_project returned a hard error rather than silently succeeding:

    > delete_project (MCP tool)
    {"error": "Permission denied"}
    
    > codebase-memory-mcp delete_project (CLI)
    Error: Permission denied
    

    This is consistent with your root-cause analysis: orphan codebase-memory-mcp.exe processes (3 in our case, visible via Get-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 without FILE_SHARE_DELETE returns ERROR_SHARING_VIOLATION, surfaced to the caller as Permission denied. So delete_project's file-deletion path hits the same lock that's blocking the WAL checkpoint — but instead of silently no-op-ing the way index_repository does, it fails loudly.

    Relevant to your proposed fix list:

    On delete_project: issue PRAGMA wal_checkpoint(TRUNCATE) before touching files on disk.

    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:

    • detect orphan stdio-spawned siblings and signal them to release before attempting checkpoint + unlink, or
    • open all SQLite handles with FILE_SHARE_DELETE (SQLITE_OPEN_DELETEONCLOSE-adjacent semantics) from the start so unlink succeeds even with concurrent readers, or
    • ship a cbm cleanup / cbm reset subcommand that does the taskkill + delete dance reliably and document it in the troubleshooting section.

    Workaround confirmed

    The exact workaround from your issue body resolves it on Windows too:

    Get-Process -Name 'codebase-memory-mcp' -ErrorAction SilentlyContinue | Stop-Process -Force
    Remove-Item "$env:USERPROFILE\.cache\codebase-memory-mcp\<project>.db*"
    # Restart Claude Code → "Index this project"

    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.

  4. fracampit commented on May 24, 2026

    @fracampit

    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.exe process, no orphans) refuted the "silent no-op" symptom entirely:

    1. Killed all codebase-memory-mcp.exe processes, deleted the project's .db* files, ran codebase-memory-mcp cli index_repository '{"repo_path":"..."}' — fresh graph built cleanly (10,858 nodes / 15,927 edges on a 1323-file TS monorepo).

    2. Immediately re-indexed (no code changes between calls):

      level=info msg=pipeline.discover files=1323 elapsed_ms=173
      level=info msg=pipeline.route path=incremental stored_hashes=1323
      level=info msg=incremental.classify changed=0 unchanged=1323 deleted=0
      level=info msg=incremental.noop reason=no_changes
      

      Returned the same counts. Honest, explicit noop logging — not silent.

    3. Re-indexed a second project (also previously indexed): same honest noop behavior.

    4. 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.exe processes holding open SQLite handles on the same project's .db / .db-wal / .db-shm files. 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 in index_repository.

    Implications for the proposed fix list in this issue

    The fix proposals here are still right — wal_checkpoint(TRUNCATE) on delete_project, stale-WAL detection on startup, SIGTERM/EOF handler, README troubleshooting docs. The Windows delete_project Permission denied manifestation I described still holds (open file handles → unlink() returns ERROR_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.

  5. added a commit that references this issue on May 28, 2026
    224d16a
  6. added a commit that references this issue on May 30, 2026
    a6ad401
  7. added a commit that references this issue on May 31, 2026
    1c00e92
  8. nwn900 commented on Jun 19, 2026

    @nwn900

    I have the following issue too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstability/performanceServer crashes, OOM, hangs, high CPU/memorywindowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions