Primary MCP server attaches to a linked project's daemon → all tools fail with -32603 "sending <op>" #7
Labels
No labels
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
h-dv/code-index#7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
In a workspace with a linked dependency project, the primary MCP server attached to the linked project's daemon instead of its own. Every tool call then returned a JSON-RPC
-32603internal error (sending stats,sending file_outline,sending search_symbols, …) because the daemon was serving a different repo root than the one being queried. Reconnecting the MCP server resolved it.Two distinct defects:
Version
code-index-mcp 0.3.1code-index-daemon 0.3.1(installed at/usr/local/bin/)2025-11-25; clientclaude-code 2.1.168v0.4.1was available but not installed (not yet tested against this bug).Symptoms
All code-index tools failed identically. Verbatim errors (JSON-RPC
-32603= Internal error):The message is always
sending <operation>. Nothing was logged to the server's stderr for these — only startup lines appear in the MCP client log.Root cause
Workspace layout (primary + one linked dependency):
ixt-iam)…/modules/ixt-iamixt)…/rust/ixtThe primary server's startup log:
Port
40899/ pid2630659belongs to the linkedixtproject (DB…/rust/ixt/.code-index/index.db). The primary server should have attached to port45569/ pid94831— its own daemon, alive, listening, and correctly recorded in…/ixt-iam/.code-index/daemon.toml. Because it queried a daemon scoped to a different root, every request errored with-32603.Both daemons were confirmed alive and listening (
ss -ltnp). Timing: the primary daemon had ~34s uptime while the linked daemon had ~1 day — consistent with a race where the newly-spawned primary daemon was ignored in favor of an already-listening daemon during discovery.Reproduction (suspected)
[[links]]dependency on project B.-32603 sending <op>.Expected
The MCP server must attach to (or spawn) the daemon whose
root/db matches its own primary root, never a linked project's daemon. Daemon discovery should key on root, not just "first listening daemon found."Workaround
Reconnect/restart the MCP server (or kill both daemons so they respawn). After reconnect, the primary log read
attached to existing daemon port=45569and all tools returned correct primary-scoped data.Suggested fixes
-32603 sending <op>with no server-side trace.v0.4.1to confirm whether either defect is already addressed.Investigation update (reviewed against current
v0.4.2)Thanks for the unusually thorough report — the daemon table and logs made this tractable. After a deep review of the current code, the diagnosis is partially corrected:
The "primary attached to the linked daemon" reading is a misattribution
With a correct primary lockfile (port
45569, exactly as you documented), the attach path reads<primary_root>/.code-index/daemon.tomland can only ever reach45569— it is structurally incapable of attaching to the linked daemon at40899. Theattached to existing daemon port=40899line you saw was almost certainly the linked project's own attach log: that log line carries onlyport+pidand no project tag, so it reads identically for primary and links. That observability gap is the first thing we're fixing.What actually caused the outage
RpcIndexcaches a single persistent TCP connection at startup with no reconnect and no health re-check. When the daemon that connection points to dies, restarts, or idle-times-out, every subsequent tool call writes to a dead socket →-32603 sending <op>indefinitely, until the MCP server is restarted. That precisely matches your symptoms (all tools fail identically; reconnecting the server fixes it). This is the real root cause and is high severity.Confirmed defects we're fixing (target:
v0.5.0)RpcIndexnever reconnects — a dead/restarted daemon bricks all calls until MCP restart. (the real trigger)Stats/Lockfilecarry noroot, so attach can't verify the daemon on a given port serves the expected repo. Latent here, but it's the genuine "wrong daemon" hazard, and it's what makes a safe reconnect possible. We're adding an optionalrootto the stats handshake (wire-compatible) and rejecting mismatches.tracing; daemon-side write failures logged atdebug!only. Both the silent failure and this misdiagnosis trace back to this.rootin the lockfile payload + nested-link handling.All wire changes are backward/forward compatible (new optional fields, old daemons still accepted). A regression test will kill a daemon under a live MCP connection and assert tool calls recover.
Will update here when
v0.5.0ships.Verified fixed. After reconnecting the MCP server, the primary server attaches to its own daemon and all previously-failing tools return correct primary-scoped results:
project_overview→ 133 files / 1610 symbols, entry pointsrc/lib.rs, 0 parse errors (correct primary index, not the linkedixtproject)search_symbols→ resolves primary symbols, taggedproject: primaryfile_outline→ returns structure cleanlyNo more
-32603 sending <op>errors. Closing.Fixed in v0.5.0 ✅
Released: v0.5.0 (PR #8). Binaries published for linux x86_64 (glibc + musl), linux aarch64, and windows x86_64 — each with a
.sha256.What landed:
code-index-mcpnow re-establishes its daemon connection on a transport failure (re-reads the lockfile, reconnects to the current port, retries once) instead of bricking every call with-32603 sending <op>until you restart it. This is the fix for your actual outage.rootin the stats response and in the lockfile payload; the MCP server verifies it on both attach and reconnect and refuses a daemon serving a different project. Closes the "wrong daemon" hazard at its source.-32603 sending <op>you saw will now have a server-side trace), and attach logs are tagged withrootso the primary's daemon is distinguishable from a link's in the log.All wire changes are backward/forward compatible, so a v0.5.0 MCP server works against an older daemon and vice versa.
Note on the original diagnosis: as covered above, the "primary attached to the linked daemon" reading was a misattribution — the per-root lockfile discovery can't structurally reach a link's port, and the un-tagged attach log made the link's own line look like the primary's. The real trigger was the missing reconnect. Both the symptom and the latent identity gap are now fixed.
To pick it up: install the v0.5.0
code-index-mcpandcode-index-daemon(kill any running daemons so they respawn on the new build). Thanks again for the detailed report — the daemon/port table is what made this fast to pin down.