geektutu/7days-golang · error
reading response body: %v
Error message
reading response body: %v
What it means
The day6-single-flight httpGetter wraps ioutil.ReadAll failures on the peer's 200 response as "reading response body: %v". The connection was established and headers received, but the body stream broke. Because of single-flight, one broken read fails every concurrent caller of that key.
Source
Thrown at gee-cache/day6-single-flight/geecache/http.go:122
u := fmt.Sprintf(
"%v%v/%v",
h.baseURL,
url.QueryEscape(group),
url.QueryEscape(key),
)
res, err := http.Get(u)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("server returned: %v", res.Status)
}
bytes, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("reading response body: %v", err)
}
return bytes, nil
}
var _ PeerGetter = (*httpGetter)(nil)
View on GitHub (pinned to cf36443821)
Solutions
- Retry the operation — with single-flight the retry collapses into a fresh peer fetch
- Set an explicit, adequate http.Client.Timeout for peer requests
- Check for intermediary (proxy/LB) response timeouts and raise them
- Capture the wrapped cause (context deadline exceeded vs connection reset) to target the fix
Example fix
// before
client := &http.Client{} // unbounded/hanging reads
// after
client := &http.Client{Timeout: 5 * time.Second}
// caller side retry:
var v ByteView
var err error
for i := 0; i < 2 && err != nil; i++ {
v, err = g.Get(key)
} Defensive patterns
Strategy: retry
Validate before calling
client := &http.Client{Timeout: 5 * time.Second}
// pre-flight: ensure the request context is still alive
select {
case <-ctx.Done():
return ctx.Err()
default:
} Try / catch
v, err := group.Get(key)
if err != nil && strings.Contains(err.Error(), "reading response body") {
// single-flight collapses concurrent retries; one retry is enough
time.Sleep(100 * time.Millisecond)
return group.Get(key)
} Prevention
- Use bounded client timeouts so a stuck read fails fast and can retry
- Check pod stability (OOM kills cut responses mid-stream) in orchestrated environments
- Keep proxy/LB response timeouts comfortably above worst-case peer fetch time
- Distinguish timeout vs reset in the wrapped message to target fixes
When it happens
Trigger: Peer connection reset during body transfer; http.Client timeout firing mid-read; peer killed after sending response headers while N waiters are pinned to the same flight.
Common situations: Pod/OOM kills mid-response in k8s; LB or proxy cutting long responses; too-aggressive client timeouts; unstable network in dev clusters.
Related errors
- reading response body: %v
- reading response body: %v
- server returned: %v
- server returned: %v
- server returned: %v
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/952634f7e4f6a670.
Report an issue: GitHub.