{"record":{"id":"6b1da3cbcd6f2049","repo":"geektutu/7days-golang","slug":"reading-body-6b1da3","errorCode":null,"errorMessage":"reading body ","messagePattern":"reading body ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day6-load-balance/client.go","lineNumber":157,"sourceCode":"\tfor err == nil {\n\t\tvar h codec.Header\n\t\tif err = client.cc.ReadHeader(&h); err != nil {\n\t\t\tbreak\n\t\t}\n\t\tcall := client.removeCall(h.Seq)\n\t\tswitch {\n\t\tcase call == nil:\n\t\t\t// it usually means that Write partially failed\n\t\t\t// and call was already removed.\n\t\t\terr = client.cc.ReadBody(nil)\n\t\tcase h.Error != \"\":\n\t\t\tcall.Error = fmt.Errorf(h.Error)\n\t\t\terr = client.cc.ReadBody(nil)\n\t\t\tcall.done()\n\t\tdefault:\n\t\t\terr = client.cc.ReadBody(call.Reply)\n\t\t\tif err != nil {\n\t\t\t\tcall.Error = errors.New(\"reading body \" + err.Error())\n\t\t\t}\n\t\t\tcall.done()\n\t\t}\n\t}\n\t// error occurs, so terminateCalls pending calls\n\tclient.terminateCalls(err)\n}\n\n// Go invokes the function asynchronously.\n// It returns the Call structure representing the invocation.\nfunc (client *Client) Go(serviceMethod string, args, reply interface{}, done chan *Call) *Call {\n\tif done == nil {\n\t\tdone = make(chan *Call, 10)\n\t} else if cap(done) == 0 {\n\t\tlog.Panic(\"rpc client: done channel is unbuffered\")\n\t}\n\tcall := &Call{\n\t\tServiceMethod: serviceMethod,","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day6-load-balance/client.go#L139-L175","documentation":"In receive(), after a successful header the client reads the response body into call.Reply; if ReadBody fails, the call's Error is set to \"reading body \" + the underlying error. This means the response header arrived but the payload could not be decoded or read. The connection is then terminated and pending calls are cleaned up.","triggerScenarios":"Codec cannot decode the body into the caller's reply type (type mismatch between client reply and server handler's out parameter); truncated/corrupted body on the wire; server wrote a body with a different codec than negotiated.","commonSituations":"Reply argument is a non-pointer or a type incompatible with the server's response; mismatched struct definitions between client and server after an API change; network interruption mid-response.","solutions":["Ensure reply passed to Call is a non-nil pointer whose type matches what the server handler writes","Keep request/response struct definitions in a shared package so both sides agree","Inspect the wrapped underlying error (suffix of the message) for the codec's real cause","Reconnect and retry: the connection was terminated after this error"],"exampleFix":"// before\nvar reply map[string]int // mismatched with server's []string response\nclient.Call(ctx, \"Foo.Bar\", args, &reply)\n\n// after\ntype FooBarReply struct { Items []string }\nreply := &FooBarReply{}\nif err := client.Call(ctx, \"Foo.Bar\", args, reply); err != nil { ... }","handlingStrategy":"validation","validationCode":"// ensure reply is a non-nil pointer before calling\nfunc validateReply(reply interface{}) error {\n    rv := reflect.ValueOf(reply)\n    if rv.Kind() != reflect.Ptr || rv.IsNil() {\n        return errors.New(\"reply must be a non-nil pointer\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := client.Call(ctx, \"Foo.Bar\", args, reply); err != nil {\n    if strings.HasPrefix(err.Error(), \"reading body \") {\n        // log strings.TrimPrefix(err.Error(), \"reading body \") for the codec cause; reconnect\n    }\n}","preventionTips":["Share request/reply struct definitions between client and server via a common package","Always pass a pointer as reply and keep its type aligned with the handler's output","Bump protocol/codec versions together on both sides when changing message shapes","Log the wrapped underlying error to distinguish decode failures from truncated reads"],"tags":["rpc","codec","deserialization","go"],"backgroundTag":"rpc-response-decode-failed","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}