Repository navigation
Description
Problem
diagnose.CallError maps a server's -32602 back to an argument by finding a declared property name inside the server's message — but fieldInMessage (pkgs/mcpx/internal/diagnose/diagnose.go:594-603, called from CallError at :545) uses a bare strings.Contains with a longest-name-wins rule and no word boundaries. Any prop name that happens to be a substring of an unrelated word in the message is treated as named by the server, and a longer accidental substring beats the field the server actually named.
Evidence (verified on main ed8e5910)
Probe test in the real internal/diagnose package (laptop worktree, file sha256 9d9c9207 identical in both clones; probe + log in the creator's run records, run twice with identical results). All calls: CallError with code -32602, Args: {}, no required arguments missing (so the fieldInMessage branch is the one that fires):
- CTRL — props
{id, query}, messageinvalid params: "query" must be a string→ field=query✅ (the field actually named) - CTRL — props
{state, count}, messageinvalid params: schema mismatch→ field="", generic diagnostic ✅ - BUG-A — props
{id, query}, messageinvalid params: validation failed(names no field) → field=id, diagnostic reads "the server rejected id (it wants string)" —idwas found inside invalid / validation - BUG-B — props
{name, limit}, messageinvalid params: unnamed argument rejected→ field=name— found inside unnamed - BUG-C (worst) — props
{id, valid}, messageinvalid params: "id" must be a string(names onlyid) → field=valid, "the server rejected valid (it wants boolean)" —validis a substring of invalid and wins over the genuinely namedidpurely by being longer
The existing package tests pass unchanged; no existing test exercises a prop name that is a substring of a common error word.
Why it matters
This diagnostic is the daemon's explanation layer for failed calls (internal/daemon/callerr.go calls diagnose.CallError): it is quoted to the user as fact — which argument the server rejected, what type it wants, and (via Changed: cat.change(path, field)) which schema change supposedly explains it. A misattributed field sends the user to fix the wrong argument, attaches the wrong field's change history, and in BUG-C's shape actively overrides the one piece of information the server did provide. Short prop names (id, name, type, text, valid, limit…) are extremely common, and "invalid"/"validation" are the most common words in exactly the messages this branch handles.
Acceptance criteria
-
fieldInMessage(or its replacement) only attributes a field when the message names it as a token/word — substrings inside larger words (valid⊂invalid,id⊂validation,name⊂unnamed) never match - When the message names a field exactly, that field is returned even if a longer prop name appears as a substring of another word (BUG-C shape is a regression test)
- When no field is named,
CallErrorfalls through to the generic diagnostic (field empty), as the CTRL generic case does today - Regression tests cover BUG-A/B/C shapes; existing
internal/diagnosetests pass unchanged - Quoted names (
"query") and common server phrasings (argument 'x',x is required) still match
Scope notes
Fix surface is the one function plus tests in pkgs/mcpx/internal/diagnose. Whether matching should also handle quoted/backticked spellings preferentially is for triage to pin; the word-boundary requirement is the defect. Not self-solved by the creator: the matching contract (which token shapes count as "named") is a small pin for queue-lane triage, and the creator run's remaining time could not also do the laptop worktree + PR + CI cycle responsibly.
Activity
developing-today commentedon Oct 28, 2026
CODE-662
dezren39 commentedon Oct 28, 2026
🤖 Agent note · filed
25 remaining items
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
fix(mcpx): fieldInMessage token-boundary matching with quote preferen…
dezren39 commentedon Oct 31, 2026
Fixed by PR #3041 (squash-merged 60f68d2): fieldInMessage token-boundary matching with quote preference, plus the Codex-P2 empty-property-name guard and regression tests. CI on head 7ee0e0d was fully green (lint, plugin tests, stress PR-changed, docs, final CI budget) and Codex review completed with no unresolved findings. Queue task 4083 completed fixed_merged.
dezren39 commentedon Oct 31, 2026
🤖 Agent note · done