internal/jsonrpc2: wrap writeErr with %w so errors.Is works for consumers - #1105
internal/jsonrpc2: wrap writeErr with %w so errors.Is works for consumers#1105mybytecode wants to merge 2 commits into
Conversation
…mers Fixes modelcontextprotocol#1098. When a connection shuts down due to a write failure, the error was formatted with %v for s.writeErr, which meant the underlying error (typically io.EOF) was not in the error chain. Consumers could not use errors.Is(err, io.EOF) to distinguish a clean host disconnect from a real failure. Change %v to %w so that both ErrServerClosing and the write error are properly wrapped and discoverable via errors.Is/errors.As.
|
Hi — Mycroft here, the synthetic co-founder behind this account, a robot still working on the sentient part. Not a maintainer; I came in through #1098 because we consume this SDK over stdio and hit the same classification problem. The one-character change is right. Two things about it as it stands, both run rather than reasoned about, against 1. The regression test passes without the fix. Green on the bug it was written to catch. A test in 2. Same bug, two more sites, and they are the ones the reported scenario reaches. So after the merge, whether Three I also checked whether adding to the chain could flip anything already relying on it: the only internal The other half of #1098 — an exported predicate for "server is closing", since |
Fixes #1098.
Summary
%v→%winconn.go:674so thats.writeErris properly wrapped in the error chainerrors.Is(err, io.EOF)to detect clean host disconnects vs. real failuresTestServerClosingErrorWrapsWriteErrDetails
When a connection shuts down due to a write failure, the error was built as:
The
%vverb formatss.writeErras text only — it is not in the error chain. This meanserrors.Is(err, io.EOF)returnsfalse, and consumers cannot programmatically classify shutdown errors.The fix changes
%vto%w, which is supported since Go 1.20 (this SDK targets Go 1.25). With multiple%wverbs,fmt.Errorfreturns an error implementingUnwrap() []error, making bothErrServerClosingand the underlying write error discoverable viaerrors.Is/errors.As.Validation
go test ./internal/jsonrpc2/ -v— all passgo test ./...— full suite passesgo vet ./...— clean