hyperledger/fabric · error

invalid response received from CouchDB

Error message

invalid response received from CouchDB

What it means

After handleRequest returns from the CreateIndex POST, the client checks that a non-nil *http.Response came back. A nil response with a nil error means the retry/existence-handling logic could not produce a usable response, so 'invalid response received from CouchDB' is returned. It guards against dereferencing a nil resp.

Source

Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdb.go:1170

	}

	indexURL, err := url.Parse(dbclient.couchInstance.url())
	if err != nil {
		couchdbLogger.Errorf("URL parse error: %s", err)
		return nil, errors.Wrapf(err, "error parsing CouchDB URL: %s", dbclient.couchInstance.url())
	}

	// get the number of retries
	maxRetries := dbclient.couchInstance.conf.MaxRetries

	resp, _, err := dbclient.handleRequest(http.MethodPost, "CreateIndex", indexURL, []byte(indexdefinition), "", "", maxRetries, true, nil, "_index")
	if err != nil {
		return nil, err
	}
	defer closeResponseBody(resp)

	if resp == nil {
		return nil, errors.New("invalid response received from CouchDB")
	}

	// Read the response body
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(err, "error reading response body")
	}

	couchDBReturn := &createIndexResponse{}

	jsonBytes := respBody

	// unmarshal the response
	err = json.Unmarshal(jsonBytes, &couchDBReturn)
	if err != nil {
		return nil, errors.Wrap(err, "error unmarshalling json data")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check whether the index already exists (the rich API's IndexExists) before creating it again
  2. Inspect handleRequest retry behavior: verify MaxRetries/connection settings in couchDBConfig
  3. Confirm CouchDB reachability (curl host:5984/_up) so handleRequest returns a real response
  4. Update Fabric if you rely on CreateIndex idempotency; newer versions surface the underlying error instead

Example fix

// before
err := indexDescription.CreateIndexIfNotExists()
// after: pre-check existence
exists, err := db.IsBulkMutable / indexExists(ddoc, name)
if err == nil && !exists {
    err = indexDescription.CreateIndexIfNotExists()
}
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check to avoid the already-exists short-circuit path
_, err := http.Get(fmt.Sprintf("http://%s/db/_index", couchAddr))
// or in chaincode use GetQueryResult with the index's fields to confirm usability

Try / catch

err := idxDef.CreateIndexIfNotExists()
if err != nil && strings.Contains(err.Error(), "invalid response received from CouchDB") {
    // verify index existence another way instead of failing hard
    return checkIndexUsableViaQuery()
}

Prevention

When it happens

Trigger: Calling CreateIndex when handleRequest exhausts retries or short-circuits (e.g. index already exists handling path) and returns (nil, nil) instead of a live HTTP response.

Common situations: Repeated CreateIndex calls with the same design doc/name hitting the already-exists path; all connection attempts failing silently after MaxRetries; misconfigured retry settings combined with transient network failures.

Related errors


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