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

  1. Verify server and client use compatible versions/codecs (same MagicNumber/CodecType handshake)
  2. Make the reply argument a non-nil pointer of the exact type the server method produces
  3. Inspect server logs for panics during method execution
  4. 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

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.