Bug description
When a force reindex clears the Milvus collection, the snapshot file (~/.context/mcp-codebase-snapshot.json) is written with indexedFiles: 0, totalChunks: 0. If the subsequent indexing fails (network error, OOM, process killed, etc.), the snapshot is left at 0/0 permanently with status completed or indexfailed.
Every new Claude Code session sees the 0/0 entry, treats it as "not indexed", and the client passes force: true to index_codebase. This nukes the real Milvus collection (which may still have valid data) and writes 0/0 again — creating an infinite reindex loop.
Reproduction steps
- Index a codebase successfully (e.g. 13,000+ chunks)
- Kill the MCP server process mid-reindex (or simulate a network failure to the embeddings server)
- Observe
~/.context/mcp-codebase-snapshot.json — the entry will show indexedFiles: 0, totalChunks: 0
- Start a new Claude Code session in that project
- The session calls
index_codebase with force: true because the snapshot says 0/0
- This nukes the Milvus collection and writes 0/0 again
- Repeat forever
Root cause
Three interacting issues:
1. Recovery path hardcodes 0/0
In handlers.ts, the search fallback recovery writes:
this.snapshotManager.setCodebaseIndexed(absolutePath,
{ indexedFiles: 0, totalChunks: 0, status: completed as const });
It never queries Milvus for actual row counts.
2. No startup validation against Milvus
loadCodebaseSnapshot() in snapshot.ts loads the snapshot from disk as-is. The v0.1.5 fix (PR #282) resets indexing entries to indexfailed, but does NOT validate completed entries with 0/0 stats against the actual Milvus backend. There is no check that says "this entry claims 0 files indexed — does the collection actually have data?"
3. Force reindex writes 0/0 before indexing starts
In handlers.ts:
this.snapshotManager.setCodebaseIndexing(absolutePath, 0);
this.snapshotManager.saveCodebaseSnapshot();
If indexing fails after this point, the snapshot has 0/0 and the v0.1.5 startup fix converts it to indexfailed — but the real collection data was already nuked by the force path.
Observed behavior
Current snapshot on my system shows 4 of 5 codebases at 0/0 despite having real Milvus collections with data:
indexed files= 0 chunks= 0 /home/eric/bu-aws (Milvus: 13,395 rows)
indexed files= 0 chunks= 0 /home/eric/ln-marketing-brief (Milvus: 23 rows)
indexed files= 0 chunks= 0 /home/eric/page-toolkit (Milvus: 474 rows)
indexed files= 0 chunks= 0 /home/eric/wow-addons (Milvus: 87 rows)
indexed files= 918 chunks= 2525 /bulk-storage/repos/mission-control (OK)
Manually patching the snapshot to reflect real Milvus row counts fixes it temporarily, but the bug re-triggers within hours.
Suggested fix
-
Startup validation: In loadCodebaseSnapshot(), for any entry with status: completed and indexedFiles: 0, totalChunks: 0, query Milvus collection.stats() for actual row count. If the collection exists with data, update the snapshot. If no collection exists, remove the entry.
-
Recovery path should query stats: Change the search fallback recovery from hardcoded { indexedFiles: 0, totalChunks: 0 } to querying actual Milvus collection stats before writing the snapshot entry.
-
Never write completed with 0/0: setCodebaseIndexed should reject or warn when called with zero files — either get real stats or mark as needs-reindex.
Environment
@zilliz/claude-context-mcp v0.1.6 (latest as of 2026-04-01)
- Milvus 2.x (self-hosted via Docker)
- Self-hosted embeddings server
- Claude Code CLI
Related issues
Bug description
When a force reindex clears the Milvus collection, the snapshot file (
~/.context/mcp-codebase-snapshot.json) is written withindexedFiles: 0, totalChunks: 0. If the subsequent indexing fails (network error, OOM, process killed, etc.), the snapshot is left at 0/0 permanently with statuscompletedorindexfailed.Every new Claude Code session sees the 0/0 entry, treats it as "not indexed", and the client passes
force: truetoindex_codebase. This nukes the real Milvus collection (which may still have valid data) and writes 0/0 again — creating an infinite reindex loop.Reproduction steps
~/.context/mcp-codebase-snapshot.json— the entry will showindexedFiles: 0, totalChunks: 0index_codebasewithforce: truebecause the snapshot says 0/0Root cause
Three interacting issues:
1. Recovery path hardcodes 0/0
In
handlers.ts, the search fallback recovery writes:It never queries Milvus for actual row counts.
2. No startup validation against Milvus
loadCodebaseSnapshot()insnapshot.tsloads the snapshot from disk as-is. The v0.1.5 fix (PR #282) resetsindexingentries toindexfailed, but does NOT validatecompletedentries with 0/0 stats against the actual Milvus backend. There is no check that says "this entry claims 0 files indexed — does the collection actually have data?"3. Force reindex writes 0/0 before indexing starts
In
handlers.ts:If indexing fails after this point, the snapshot has 0/0 and the v0.1.5 startup fix converts it to
indexfailed— but the real collection data was already nuked by the force path.Observed behavior
Current snapshot on my system shows 4 of 5 codebases at 0/0 despite having real Milvus collections with data:
Manually patching the snapshot to reflect real Milvus row counts fixes it temporarily, but the bug re-triggers within hours.
Suggested fix
Startup validation: In
loadCodebaseSnapshot(), for any entry withstatus: completedandindexedFiles: 0, totalChunks: 0, query Milvuscollection.stats()for actual row count. If the collection exists with data, update the snapshot. If no collection exists, remove the entry.Recovery path should query stats: Change the search fallback recovery from hardcoded
{ indexedFiles: 0, totalChunks: 0 }to querying actual Milvus collection stats before writing the snapshot entry.Never write completed with 0/0:
setCodebaseIndexedshould reject or warn when called with zero files — either get real stats or mark as needs-reindex.Environment
@zilliz/claude-context-mcpv0.1.6 (latest as of 2026-04-01)Related issues