{"record":{"id":"f1df012120ef57e6","repo":"hyperledger/fabric","slug":"http-error-calling-couchdb","errorCode":null,"errorMessage":"http error calling couchdb","messagePattern":"http error calling couchdb","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go","lineNumber":1716,"sourceCode":"\t\t\t\tcouchdbLogger.Warningf(\"Attempt %d of %d returned Couch DB Error:%s,  Status Code:%v  Reason:%s. %s\",\n\t\t\t\t\tattempts+1, maxRetries+1, couchDBReturn.Error, resp.Status, couchDBReturn.Reason, retryMessage)\n\n\t\t\t}\n\t\t\t// if there are more retries remaining, sleep for specified sleep time, then retry\n\t\t\tif attempts < maxRetries {\n\t\t\t\ttime.Sleep(waitDuration)\n\t\t\t}\n\n\t\t\t// backoff, doubling the retry time for next attempt\n\t\t\twaitDuration *= 2\n\n\t\t}\n\n\t} // end retry loop\n\n\t// if a golang http error is still present after retries are exhausted, return the error\n\tif errResp != nil {\n\t\treturn nil, couchDBReturn, errors.Wrap(errResp, \"http error calling couchdb\")\n\t}\n\n\t// This situation should not occur according to the golang spec.\n\t// if this error returned (errResp) from an http call, then the resp should be not nil,\n\t// this is a structure and StatusCode is an int\n\t// This is meant to provide a more graceful error if this should occur\n\tif invalidCouchDBReturn(resp, errResp) {\n\t\treturn nil, nil, errors.New(\"unable to connect to CouchDB, check the hostname and port\")\n\t}\n\n\t// set the return code for the couchDB request\n\tcouchDBReturn.StatusCode = resp.StatusCode\n\n\t// check to see if the status code from couchdb is 400 or higher\n\t// response codes 4XX and 500 will be treated as errors -\n\t// golang error will be created from the couchDBReturn contents and both will be returned\n\tif resp.StatusCode >= http.StatusBadRequest {\n","sourceCodeStart":1698,"sourceCodeEnd":1734,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go#L1698-L1734","documentation":"After all retry attempts are exhausted, if the golang http client itself returned an error (errResp) from the HTTP call — never getting a valid HTTP response — handleRequest wraps it as \"http error calling couchdb\". It means the peer could not be reached or the request failed at the transport level across every attempt.","triggerScenarios":"Connection refused/timeout/DNS failure to the CouchDB host on every retry; TLS handshake failure; request context cancelled after retries exhausted.","commonSituations":"CouchDB container stopped; wrong hostname/port in core.yaml; firewall or network policy blocking the peer-to-CouchDB port; expired TLS certificates.","solutions":["Verify CouchDB is running and reachable (curl the CouchDB URL from the peer host)","Check the couchDB address/port and credentials in core.yaml","Check network policy/firewall rules and TLS certificate validity","Increase maxRetries and retryWaitTime if CouchDB is intermittently unavailable"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight connectivity check before opening the ledger\nresp, err := http.Get(\"http://couchdb:5984/_up\")\nif err != nil { return fmt.Errorf(\"CouchDB unreachable: %w\", err) }","typeGuard":null,"tryCatchPattern":"_, _, err := handleRequest(...)\nif err != nil && strings.Contains(err.Error(), \"http error calling couchdb\") {\n    // all retries failed at transport level: alert and back off hard\n}","preventionTips":["Add readiness checks for CouchDB before peer start","Validate hostname/port/credentials in core.yaml at deployment","Monitor DNS, firewall rules, and TLS cert expiry"],"tags":["network","http","couchdb","connection"],"backgroundTag":"connection-refused","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"}