{"record":{"id":"ac1ab3579ae73fbb","repo":"micro/go-micro","slug":"failed-to-close-body","errorCode":null,"errorMessage":"failed to close body","messagePattern":"failed to close body","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"transport/http_client.go","lineNumber":159,"sourceCode":"\t\t\treturn err\n\t\t}\n\t}\n\n\th.Lock()\n\tdefer h.Unlock()\n\n\tif h.closed {\n\t\treturn io.EOF\n\t}\n\n\trsp, err := http.ReadResponse(h.buff, req)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err2 := rsp.Body.Close(); err2 != nil {\n\t\t\terr = errors.Wrap(err2, \"failed to close body\")\n\t\t}\n\t}()\n\n\tb, err := io.ReadAll(rsp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn errors.New(rsp.Status + \": \" + string(b))\n\t}\n\n\tmsg.Body = b\n\n\tif msg.Header == nil {\n\t\tmsg.Header = make(map[string]string, len(rsp.Header))\n\t}\n","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/transport/http_client.go#L141-L177","documentation":"The HTTP transport client's Recv (message receive) defers a Body.Close and, if closing the response body fails, rewrites the pending error with 'failed to close body'. It signals the HTTP response body could not be cleanly closed — usually a symptom of an underlying connection/socket problem rather than a logic bug in caller code.","triggerScenarios":"Receiving a streaming/published message over the http transport when rsp.Body.Close() returns an error: connection reset by peer mid-close, already-broken socket, or server abruptly terminating the response.","commonSituations":"Server behind a load balancer that kills idle keep-alive connections; client timeouts cutting the connection while the body is being closed; remote service crashing during a streaming response.","solutions":["Inspect the wrapped cause — it usually reflects an already-dead connection; treat as a transport-level failure and retry the request.","Enable/disable keep-alives or tune client timeouts so connections aren't severed mid-close.","Check server/load-balancer idle timeout settings versus client usage patterns.","Retry the receive operation; this error is typically transient.","Verify network stability between client and the HTTP transport server."],"exampleFix":"// before\nmsg, err := sock.Recv() // transient: failed to close body\nif err != nil { return err }\n// after\nmsg, err := sock.Recv()\nif err != nil {\n\tif isTransientNetErr(err) { // includes wrapped 'failed to close body'\n\t\treturn retry(sock.Recv)\n\t}\n\treturn err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isBodyCloseErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to close body\")\n}","tryCatchPattern":"msg, err := client.Recv()\nif err != nil {\n\tif isBodyCloseErr(err) {\n\t\t// connection already broken; log and retry\n\t\tlog.Warn(\"body close failed (dead connection)\")\n\t\treturn retryWithBackoff(func() error { _, err = client.Recv(); return err })\n\t}\n\treturn err\n}","preventionTips":["Treat this as transient: retry the receive after reconnecting.","Align client timeouts with server/LB idle timeouts to avoid severed keep-alive connections.","Disable or tune HTTP keep-alives for long-lived streaming transports.","Monitor network stability; this error usually accompanies connection resets.","Check the wrapped cause via errors.Unwrap for the underlying net error."],"tags":["http","transport","network","connection"],"backgroundTag":"http-body-close-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}