geektutu/7days-golang · error
%s
Error message
%s
What it means
Same receive-loop failure as day2 but in gee-rpc/day3-service: reading a response body failed, so the pending Call's Error becomes "reading body <cause>" and the client tears down the connection and all in-flight calls. It means the response stream was broken or undecodable.
Source
Thrown at gee-rpc/day3-service/client.go:146
}
}
}
func (client *Client) receive() {
var err error
for err == nil {
var h codec.Header
if err = client.cc.ReadHeader(&h); err != nil {
break
}
call := client.removeCall(h.Seq)
switch {
case call == nil:
// it usually means that Write partially failed
// and call was already removed.
err = client.cc.ReadBody(nil)
case h.Error != "":
call.Error = fmt.Errorf(h.Error)
err = client.cc.ReadBody(nil)
call.done()
default:
err = client.cc.ReadBody(call.Reply)
if err != nil {
call.Error = errors.New("reading body " + err.Error())
}
call.done()
}
}
// error occurs, so terminateCalls pending calls
client.terminateCalls(err)
}
// Go invokes the function asynchronously.
// It returns the Call structure representing the invocation.
func (client *Client) Go(serviceMethod string, args, reply interface{}, done chan *Call) *Call {
if done == nil {View on GitHub (pinned to cf36443821)
Solutions
- Verify server and client use compatible versions/codecs (same MagicNumber/CodecType handshake)
- Make the reply argument a non-nil pointer of the exact type the server method produces
- Inspect server logs for panics during method execution
- Retry the call after reconnecting; the connection is dead after this error
Example fix
// before
var out Foo
client.Call("Bar.Method", req, out) // wrong: value type
// after
out := &Foo{}
if err := client.Call("Bar.Method", req, out); err != nil {
client, err = geerpc.Dial("tcp", addr, opts) // reconnect before retry
} Defensive patterns
Strategy: retry
Validate before calling
reply := &ExpectedType{}
if client == nil {
c, err := geerpc.Dial("tcp", addr, opts)
if err != nil { return err }
client = c
} Type guard
func replyIsPointer(v interface{}) bool {
rv := reflect.ValueOf(v)
return rv.IsValid() && rv.Kind() == reflect.Ptr && !rv.IsNil()
} Try / catch
err := client.Call("Bar.Method", req, reply)
if err != nil && strings.HasPrefix(err.Error(), "reading body") {
client, _ = geerpc.Dial("tcp", addr, opts)
err = client.Call("Bar.Method", req, reply)
} Prevention
- Use identical client/server versions of the library so codecs match
- Pass pointer replies matching the server's concrete reply type
- Log and alert on server panics during method execution
- Reconnect after any receive-loop failure; the client is single-use after that
When it happens
Trigger: During a Call on a day3-service client, client.cc.ReadBody(call.Reply) errors: connection reset by the server, truncated response, or Gob decode mismatch between the server's written reply and the client's reply type.
Common situations: Server-side method panics mid-write; service registered on the server writes a reply of a different concrete type; firewall/proxy drops long-lived connections; incompatible day-branch versions (server from day2, client from day3) writing mismatched streams.
Related errors
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/8f50ebcbd2996e9f.
Report an issue: GitHub.