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

  1. Check server logs for a crash or panic occurring while handling the request
  2. Ensure the reply argument is a non-nil pointer whose type matches what the server method writes
  3. Verify network stability between client and server (retries, keepalives)
  4. 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

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.