{"record":{"id":"beef618745e6cdef","repo":"hyperledger/fabric","slug":"number-of-retries-must-be-zero-or-greater","errorCode":null,"errorMessage":"number of retries must be zero or greater","messagePattern":"number of retries must be zero or greater","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go","lineNumber":1569,"sourceCode":"// If it returns an error, it ensures that the response body is closed, else it is the\n// callee's responsibility to close response correctly.\n// Any http error or CouchDB error (4XX or 500) will result in a golang error getting returned\nfunc (couchInstance *couchInstance) handleRequest(ctx context.Context, method, dbName, functionName string, connectURL *url.URL, data []byte, rev string,\n\tmultipartBoundary string, maxRetries int, keepConnectionOpen bool, queryParms *url.Values, pathElements ...string,\n) (*http.Response, *dbReturn, error) {\n\tcouchdbLogger.Debugf(\"Entering handleRequest()  method=%s  url=%v  dbName=%s\", method, connectURL, dbName)\n\n\t// create the return objects for couchDB\n\tvar resp *http.Response\n\tvar errResp error\n\tcouchDBReturn := &dbReturn{}\n\tdefer couchInstance.recordMetric(time.Now(), dbName, functionName, couchDBReturn)\n\n\t// set initial wait duration for retries\n\twaitDuration := retryWaitTime * time.Millisecond\n\n\tif maxRetries < 0 {\n\t\treturn nil, nil, errors.New(\"number of retries must be zero or greater\")\n\t}\n\n\trequestURL := constructCouchDBUrl(connectURL, dbName, pathElements...)\n\n\tif queryParms != nil {\n\t\trequestURL.RawQuery = queryParms.Encode()\n\t}\n\n\tcouchdbLogger.Debugf(\"Request URL: %s\", requestURL)\n\n\t// attempt the http request for the max number of retries\n\t// if maxRetries is 0, the database creation will be attempted once and will\n\t//    return an error if unsuccessful\n\t// if maxRetries is 3 (default), a maximum of 4 attempts (one attempt with 3 retries)\n\t//    will be made with warning entries for unsuccessful attempts\n\tfor attempts := 0; attempts <= maxRetries; attempts++ {\n\n\t\t// Set up a buffer for the payload data","sourceCodeStart":1551,"sourceCodeEnd":1587,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go#L1551-L1587","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nmaxRetries: -1\n// after\nmaxRetries: 3","handlingStrategy":"validation","validationCode":"if maxRetries < 0 {\n    return fmt.Errorf(\"couchDBConfig.maxRetries must be >= 0, got %d\", maxRetries)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["configuration","validation","retry","couchdb"],"backgroundTag":"invalid-retry-count","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}