hyperledger/fabric · error

chaincode query must have at least one chaincode interest

Error message

chaincode query must have at least one chaincode interest

What it means

validateCCQuery rejects a ChaincodeQuery whose Interests slice is empty. A chaincode discovery query exists to resolve endorsements for specific chaincodes/collections, so a query with no interests is meaningless and structurally invalid.

Source

Thrown at discovery/service.go:264

	}
	if !tlsEnabled {
		return req, nil
	}
	computedHash := certHashFromContext(ctx)
	if len(computedHash) == 0 {
		return nil, errors.New("client didn't send a TLS certificate")
	}
	if !bytes.Equal(computedHash, req.Authentication.ClientTlsCertHash) {
		claimed := hex.EncodeToString(req.Authentication.ClientTlsCertHash)
		logger.Warningf("client claimed TLS hash %s doesn't match computed TLS hash from gRPC stream %s", claimed, hex.EncodeToString(computedHash))
		return nil, errors.New("client claimed TLS hash doesn't match computed TLS hash from gRPC stream")
	}
	return req, nil
}

func validateCCQuery(ccQuery *discovery.ChaincodeQuery) error {
	if len(ccQuery.Interests) == 0 {
		return errors.New("chaincode query must have at least one chaincode interest")
	}
	for _, interest := range ccQuery.Interests {
		if interest == nil {
			return errors.New("chaincode interest is nil")
		}
		if len(interest.Chaincodes) == 0 {
			return errors.New("chaincode interest must contain at least one chaincode")
		}
		for _, cc := range interest.Chaincodes {
			if cc.Name == "" {
				return errors.New("chaincode name in interest cannot be empty")
			}
		}
	}
	return nil
}

func wrapError(err error) *discovery.QueryResult {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Add at least one ChaincodeInterest naming the chaincode(s) to discover before sending the query
  2. Fix the upstream config/lookup that produced an empty chaincode list
  3. Validate client-side that len(interests) > 0 before invoking the discovery call

Example fix

// before
query := &discovery.ChaincodeQuery{Interests: []discovery.ChaincodeInterest{}}
// after
query := &discovery.ChaincodeQuery{Interests: []discovery.ChaincodeInterest{{Chaincodes: []discovery.ChaincodeCall{{Name: "mycc"}}}}}
Defensive patterns

Strategy: validation

Validate before calling

func validateChaincodeQuery(q *discovery.ChaincodeQuery) error {
    if q == nil || len(q.Interests) == 0 {
        return errors.New("chaincode query requires at least one interest")
    }
    return nil
}

Type guard

func hasInterests(q *discovery.ChaincodeQuery) bool {
    return q != nil && len(q.Interests) > 0
}

Try / catch

if err := validateChaincodeQuery(query); err != nil {
    return fmt.Errorf("fix query before sending: %w", err)
}
resp, err := client.Send(ctx, req)
if err != nil {
    if strings.Contains(err.Error(), "at least one chaincode interest") {
        return fmt.Errorf("interests list was empty; check chaincode config: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling the chaincode discovery query (via chaincodeQuery, invoked from Discover) with a discovery.ChaincodeQuery that has zero entries in Interests.

Common situations: Building the query programmatically with an empty slice because chaincode names were read from an empty config; a filter loop that dropped all interests; SDK call where the chaincodes argument was omitted or an empty array was passed.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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