geektutu/7days-golang · error
%s
Error message
%s
What it means
This is a wrapped transport/read failure raised in Client.receive (gee-rpc/day2-client). When reading a response body fails, the pending Call's Error is set to "reading body <cause>" and the receive loop terminates, closing the connection and failing all pending calls. It indicates the connection or codec stream was corrupted or dropped mid-response.
Source
Thrown at gee-rpc/day2-client/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
- Check server logs for a crash or panic occurring while handling the request
- Ensure the reply argument is a non-nil pointer whose type matches what the server method writes
- Verify network stability between client and server (retries, keepalives)
- Re-invoke Call after the connection is re-established; the library terminates pending calls on this error
Example fix
// before
var reply string
err := client.Call("Foo.Sum", args, reply) // reply not a pointer -> decode fails
// after
reply := ""
err := client.Call("Foo.Sum", args, &reply)
if err != nil {
// reconnect and retry
} Defensive patterns
Strategy: retry
Validate before calling
reply := &MyReply{} // must be a non-nil pointer matching the server type
if client == nil {
client, err = geerpc.Dial("tcp", addr, opts)
if err != nil { return err }
} Type guard
func validReply(v interface{}) bool {
if v == nil { return false }
rv := reflect.ValueOf(v)
return rv.Kind() == reflect.Ptr && !rv.IsNil()
} Try / catch
err := client.Call("Foo.Sum", args, reply)
if err != nil {
if strings.HasPrefix(err.Error(), "reading body") {
client, err = geerpc.Dial("tcp", addr, opts) // connection is dead; reconnect
if err == nil { err = client.Call("Foo.Sum", args, reply) }
}
return err
} Prevention
- Always pass a non-nil pointer as the reply argument
- Keep server reply types and client reply types identical
- Monitor server health; a crash mid-response is the usual root cause
- Wrap Call with reconnect-and-retry logic since receive() kills the client on any read error
When it happens
Trigger: Client.Call/Go is waiting on a response; client.cc.ReadBody(call.Reply) inside receive() returns an error — e.g. server closed the TCP connection after writing the header, response bytes were truncated, or the codec (Gob) fails to decode the body into the reply type.
Common situations: Server crashes or is killed while processing the request; network interruption mid-response; reply passed as a value instead of pointer or of the wrong type so Gob decoding fails; server writes a response that the client codec cannot parse.
Related errors
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/b7f2f8f3b1a550e7.
Report an issue: GitHub.