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 data

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set maxRetries to 0 or a positive value in the CouchDB config
  2. Check core.yaml couchDB section for a negative maxRetries/maxPaginationCount value
  3. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/beef618745e6cdef. Report an issue: GitHub.