hyperledger/fabric · error
error reading response body
Error message
error reading response body
What it means
Returned when io.ReadAll(resp.Body) fails while consuming the HTTP response from a CouchDB range query. The library received an HTTP response but could not read the body stream off the wire (connection dropped mid-response, timeout, or transport reset). The raw io error is wrapped with this fixed message.
Source
Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go:890
resp, _, err := dbclient.handleRequest(http.MethodGet, "RangeDocRange", rangeURL, nil, "", "", maxRetries, true, &queryParms, "_all_docs")
if err != nil {
return nil, "", err
}
defer closeResponseBody(resp)
if couchdbLogger.IsEnabledFor(zapcore.DebugLevel) {
dump, err2 := httputil.DumpResponse(resp, false)
if err2 != nil {
log.Fatal(err2)
}
// compact debug log by replacing carriage return / line feed with dashes to separate http headers
couchdbLogger.Debugf("[%s] HTTP Response: %s", dbclient.dbName, bytes.Replace(dump, []byte{0x0d, 0x0a}, []byte{0x20, 0x7c, 0x20}, -1))
}
// handle as JSON document
jsonResponseRaw, err := io.ReadAll(resp.Body)
if err != nil {
return nil, "", errors.Wrap(err, "error reading response body")
}
jsonResponse := &rangeQueryResponse{}
err2 := json.Unmarshal(jsonResponseRaw, &jsonResponse)
if err2 != nil {
return nil, "", errors.Wrap(err2, "error unmarshalling json data")
}
// if an additional record is found, then reduce the count by 1
// and populate the nextStartKey
if jsonResponse.TotalRows > limit {
jsonResponse.TotalRows = limit
}
couchdbLogger.Debugf("[%s] Total Rows: %d", dbclient.dbName, jsonResponse.TotalRows)
// Use the next endKey as the starting default for the nextStartKey
nextStartKey := endKeyView on GitHub (pinned to 2736b63f8f)
Solutions
- Retry the range query; the error is usually transient network/transport failure.
- Check CouchDB server health/logs around the failure time for crashes or restarts.
- Reduce result-set size by narrowing the startKey/endKey or lowering limit to shorten the response window.
- Inspect network path (proxies, LB idle timeouts) between peer and CouchDB and raise timeout limits.
Defensive patterns
Strategy: retry
Validate before calling
if err := couchHealthCheck(client); err != nil {
return fmt.Errorf("couchdb unreachable before range scan: %w", err)
} Try / catch
results, err := db.RangeScan(startKey, endKey)
if err != nil && strings.Contains(err.Error(), "error reading response body") {
results, err = retryWithBackoff(3, func() ([]*queryResult, string, error) {
return db.RangeScan(startKey, endKey)
})
} Prevention
- Monitor CouchDB health (/_up) and restart-on-failure in orchestration
- Size range scans modestly; avoid huge single responses
- Remove idle-timeout proxies between peer and CouchDB or raise their limits
- Ensure stable networking (no aggressive conntrack/NAT drops) between peer and DB
When it happens
Trigger: During handleRangeQuery: the _all_docs (or _design/...) GET returns headers successfully, then the TCP connection breaks or times out while streaming the JSON body.
Common situations: CouchDB container restarted or OOM-killed mid-request, load balancer idle-timeout closing long responses, network flakiness between peer and CouchDB, or very large range scans over slow links.
Related errors
- failed to create target folder for connection.json: %s
- error reading next multipart
- error reading multipart data
- http error calling couchdb
- unable to connect to CouchDB, check the hostname and port
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d97f844f02d78469.
Report an issue: GitHub.