hyperledger/fabric · error
number of retries must be zero or greater
Error message
number of retries must be zero or greater
What it means
A defensive validation error in handleRequest: the maxRetries argument passed to the CouchDB client call was negative. Retries are a caller-supplied count and must be zero or greater; a negative value is treated as a programming mistake and rejected immediately without any HTTP call.
Source
Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go:1569
// If it returns an error, it ensures that the response body is closed, else it is the
// callee's responsibility to close response correctly.
// Any http error or CouchDB error (4XX or 500) will result in a golang error getting returned
func (couchInstance *couchInstance) handleRequest(ctx context.Context, method, dbName, functionName string, connectURL *url.URL, data []byte, rev string,
multipartBoundary string, maxRetries int, keepConnectionOpen bool, queryParms *url.Values, pathElements ...string,
) (*http.Response, *dbReturn, error) {
couchdbLogger.Debugf("Entering handleRequest() method=%s url=%v dbName=%s", method, connectURL, dbName)
// create the return objects for couchDB
var resp *http.Response
var errResp error
couchDBReturn := &dbReturn{}
defer couchInstance.recordMetric(time.Now(), dbName, functionName, couchDBReturn)
// set initial wait duration for retries
waitDuration := retryWaitTime * time.Millisecond
if maxRetries < 0 {
return nil, nil, errors.New("number of retries must be zero or greater")
}
requestURL := constructCouchDBUrl(connectURL, dbName, pathElements...)
if queryParms != nil {
requestURL.RawQuery = queryParms.Encode()
}
couchdbLogger.Debugf("Request URL: %s", requestURL)
// attempt the http request for the max number of retries
// if maxRetries is 0, the database creation will be attempted once and will
// return an error if unsuccessful
// if maxRetries is 3 (default), a maximum of 4 attempts (one attempt with 3 retries)
// will be made with warning entries for unsuccessful attempts
for attempts := 0; attempts <= maxRetries; attempts++ {
// Set up a buffer for the payload dataView on GitHub (pinned to 2736b63f8f)
Solutions
- Set maxRetries to 0 or a positive value in the CouchDB config
- Check core.yaml couchDB section for a negative maxRetries/maxPaginationCount value
- Audit any code computing retry counts at runtime for sign errors
Example fix
// before maxRetries: -1 // after maxRetries: 3
Defensive patterns
Strategy: validation
Validate before calling
if maxRetries < 0 {
return fmt.Errorf("couchDBConfig.maxRetries must be >= 0, got %d", maxRetries)
} Prevention
- Validate core.yaml couchDB maxRetries is non-negative at startup
- Use schema validation on ledger config files
- Avoid computing retry counts with subtraction that can go negative
When it happens
Trigger: Passing a negative retry count into couchdb createConnection/handleRequest callers — typically from a misconfigured retry-count setting parsed from config as a signed int (e.g. couchDBConfig.maxRetries set to -1).
Common situations: Ledger config (core.yaml couchDB maxRetries) edited by hand with a negative number; environment variable interpolation producing negative values; arithmetic computing retry counts from differences that underflow.
Related errors
- chaincode type not supported: %s
- failed to copy metadataDir directory folder: %s
- error unmarshalling YAML file %s: %s
- plugin with name %s wasn't found
- error parsing CouchDB URL: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/beef618745e6cdef.
Report an issue: GitHub.