{"record":{"id":"661a320bf4ccd9fa","repo":"OpenNHP/opennhp","slug":"could-not-read-response-body-v","errorCode":null,"errorMessage":"could not read response body: %v","messagePattern":"could not read response body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/db/utils.go","lineNumber":273,"sourceCode":"\t\tTimeout: 120 * time.Minute,\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not send https request: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tbodyBytes, _ := io.ReadAll(resp.Body)\n\n\t\treturn \"\", fmt.Errorf(\"unexpected status code: %d, content: %s\", resp.StatusCode, string(bodyBytes))\n\t}\n\n\t// read response body\n\tbodyBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not read response body: %v\", err)\n\t}\n\n\t// parse response body\n\tvar respBody ServerResponse\n\n\terr = json.Unmarshal(bodyBytes, &respBody)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not parse response body: %v\", err)\n\t}\n\n\tduration := time.Since(startTime)\n\tspeed := float64(progress.TotalSize) / duration.Seconds() / (1024 * 1024)\n\n\t// change the chinese to english\n\tfmt.Printf(\"\\nUpload %s to %s success! (time: %.2fs, speed: %.2fMB/s)\\n\",\n\t\tfilePath, httpHost+respBody.FileURI, duration.Seconds(), speed)\n\n\treturn httpHost + respBody.FileURI, nil","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/db/utils.go#L255-L291","documentation":"After a 200 response, the function reads the full response body with io.ReadAll(resp.Body). If the read fails mid-stream — connection dropped or reset before the body finished arriving, chunked-encoding error, or an idle/keep-alive read timeout — it wraps the error as \"could not read response body: %v\". The upload itself likely succeeded server-side but the client cannot confirm it.","triggerScenarios":"io.ReadAll(resp.Body) returns a non-EOF error in UploadFileToNHPServer (endpoints/db/utils.go:271-274) on a 200 response: unexpected EOF from a connection reset after headers, server closing the connection while streaming the response, intermediate proxy truncating the response, or read timeout on a stalled keep-alive connection.","commonSituations":"Flaky network or NAT dropping the connection right after the upload completes; proxy/load balancer with a short idle timeout cutting the response; server crashing mid-response; very large 200 responses interrupted on slow links.","solutions":["Retry the whole upload when the error is io.ErrUnexpectedEOF or a connection-reset, since the server state is uncertain (idempotency permitting)","Check network path stability (VPN/proxy idle timeouts) and raise proxy keep-alive/idle timeouts above the upload duration","Check server logs to see whether the upload was persisted despite the truncated response","Verify the server writes and flushes its response promptly after processing instead of holding the connection","If using a custom Transport, ensure ResponseHeaderTimeout/IdleConnTimeout are generous for long uploads"],"exampleFix":"// before\nbodyBytes, err := io.ReadAll(resp.Body)\nif err != nil {\n\treturn \"\", fmt.Errorf(\"could not read response body: %v\", err)\n}\n// after\nbodyBytes, err := io.ReadAll(resp.Body)\nif err != nil {\n\tif errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {\n\t\treturn \"\", fmt.Errorf(\"response truncated, upload result unknown, retry: %v\", err)\n\t}\n\treturn \"\", fmt.Errorf(\"could not read response body: %v\", err)\n}","handlingStrategy":"retry","validationCode":"client := &http.Client{\n\tTimeout: 120 * time.Minute,\n\tTransport: &http.Transport{\n\t\tIdleConnTimeout: 300 * time.Second,\n\t\tResponseHeaderTimeout: 120 * time.Second,\n\t},\n}\n_ = client // use generous timeouts so keep-alive reads are not cut short","typeGuard":null,"tryCatchPattern":"result, err := device.UploadFileToNHPServer(filePath)\nif err != nil && strings.Contains(err.Error(), \"could not read response body\") {\n\tif strings.Contains(err.Error(), \"unexpected EOF\") || strings.Contains(err.Error(), \"connection reset\") {\n\t\t// server may have persisted the file; verify existence before blind re-upload\n\t\treturn retryUploadWithBackoff(filePath)\n\t}\n\treturn fmt.Errorf(\"failed reading upload confirmation: %w\", err)\n}","preventionTips":["Raise proxy/load-balancer idle timeouts above the longest upload duration","Retry idempotently: verify whether the file landed on the server before re-uploading","Avoid proxies that buffer/rewrite long-running uploads when possible","Monitor server logs for crashes or truncation right after upload completion","Use a transport with generous IdleConnTimeout for large transfers"],"tags":["go","http","network","io"],"backgroundTag":"network-request-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}