# Problem
WireError.Is backs errors.Is checks used across the SDK against
sentinels such as ErrMethodNotFound, ErrRejected, and ErrClientClosing,
but had no direct test. Add a table-driven test for it.
While doing so, errors.Is(err, (*WireError)(nil)) was found to panic on
a nil pointer dereference, because Is read w.Code without a nil check.
Guard against a nil *WireError target so the comparison returns false.
```go
errors.Is(err, (*WireError)(nil)) // panic: nil pointer dereference
```
# Approach
Is read w.Code after a successful type assertion without checking
whether w itself was nil. The fix guards against a nil *WireError target
so the comparison returns false instead of panicking.
# Test plan
- go test ./internal/jsonrpc2/ passes.
- The new typed nil WireError case panics without the one-line fix and
passes with it, confirming the test exercises the guarded path.
Co-authored-by: Yaroslav <yarolegovich@gmail.com>
## Summary
Fixes#976.
`DecodeMessage` used `msg.Method != ""` to classify messages. A wire
payload with `"method":""` was decoded as a **response**, so stdio
servers dropped it without a correlated JSON-RPC error.
## Approach
Decode into a `wireDecode` struct whose `method` field is
`json.RawMessage`. Treat the message as a **request** when the `method`
key is **present on the wire** (including `""`), which matches JSON-RPC
semantics.
This revision:
- Uses a **single JSON parse** per message (dedicated decode struct, no
secondary fields-map unmarshal)
- Documents why `json.RawMessage` is used for `method`
- Adds regression coverage so normal responses and id-only payloads
without a `method` key stay on the response path
## Test plan
- [x] `go test ./internal/jsonrpc2/... -v`
- [x] `go test ./mcp/... -run TestIOConnRead_EmptyMethod -v`
- [x] `go test ./... -count=1`
- [x] `go test -race ./internal/jsonrpc2/... -count=1`
- [x] Server conformance (`npx @modelcontextprotocol/conformance server
--url http://127.0.0.1:3000/mcp`) — 40 passed, 0 failed
- [x] Client conformance (`./scripts/client-conformance.sh`) — 217
passed, 0 failed
## Scope note
This PR addresses the primary repro in #976 (empty `method` with valid
`id`). Other cases listed in the issue (`id: null`, structurally invalid
envelopes) are unchanged.
Co-authored-by: Guglielmo Colombo <guglielmoc@google.com>
Produced with a patched version of modernize containing only
the efaceany pass:
$ go run ./gopls/internal/analysis/modernize/cmd/modernize/main.go -test -fix ./... ./gopls/...
This is very safe and forms the bulk of the modernize diff,
isolating the other changes for ease of review.
Change-Id: Iec9352bac5a639a5c03368427531c7842c6e9ad0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/650759
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>