{"record":{"id":"ddf50118d3b1b736","repo":"hyperledger/fabric","slug":"chaincode-interest-is-nil-ddf501","errorCode":null,"errorMessage":"chaincode interest is nil","messagePattern":"chaincode interest is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/service.go","lineNumber":268,"sourceCode":"\tcomputedHash := certHashFromContext(ctx)\n\tif len(computedHash) == 0 {\n\t\treturn nil, errors.New(\"client didn't send a TLS certificate\")\n\t}\n\tif !bytes.Equal(computedHash, req.Authentication.ClientTlsCertHash) {\n\t\tclaimed := hex.EncodeToString(req.Authentication.ClientTlsCertHash)\n\t\tlogger.Warningf(\"client claimed TLS hash %s doesn't match computed TLS hash from gRPC stream %s\", claimed, hex.EncodeToString(computedHash))\n\t\treturn nil, errors.New(\"client claimed TLS hash doesn't match computed TLS hash from gRPC stream\")\n\t}\n\treturn req, nil\n}\n\nfunc validateCCQuery(ccQuery *discovery.ChaincodeQuery) error {\n\tif len(ccQuery.Interests) == 0 {\n\t\treturn errors.New(\"chaincode query must have at least one chaincode interest\")\n\t}\n\tfor _, interest := range ccQuery.Interests {\n\t\tif interest == nil {\n\t\t\treturn errors.New(\"chaincode interest is nil\")\n\t\t}\n\t\tif len(interest.Chaincodes) == 0 {\n\t\t\treturn errors.New(\"chaincode interest must contain at least one chaincode\")\n\t\t}\n\t\tfor _, cc := range interest.Chaincodes {\n\t\t\tif cc.Name == \"\" {\n\t\t\t\treturn errors.New(\"chaincode name in interest cannot be empty\")\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc wrapError(err error) *discovery.QueryResult {\n\treturn &discovery.QueryResult{\n\t\tResult: &discovery.QueryResult_Error{\n\t\t\tError: &discovery.Error{\n\t\t\t\tContent: err.Error(),","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/service.go#L250-L286","documentation":"validateCCQuery iterates the ChaincodeQuery's Interests and rejects any entry that is a nil pointer. A nil interest carries no chaincode information, so the server fails fast with this error rather than dereferencing nil.","triggerScenarios":"Calling the chaincode discovery query (via chaincodeQuery) with Interests containing a nil *discovery.ChaincodeInterest element, e.g. a slice built with make([]discovery.ChaincodeInterest, n) and partially filled, or appending a nil pointer.","commonSituations":"Pre-allocating an interests slice of fixed size and only populating some entries; a JSON/config deserialization that produced null entries; an append that mistakenly added an uninitialized pointer.","solutions":["Ensure every element of Interests is a non-nil ChaincodeInterest; filter out nils before sending","Avoid pre-allocating with make(..., n) and leaving entries unset; build with append","Add a client-side loop checking each interest for nil before invoking discovery"],"exampleFix":"// before\ninterests := make([]discovery.ChaincodeInterest, len(names)) // trailing entries nil\n// after\nvar interests []discovery.ChaincodeInterest\nfor _, n := range names {\n    interests = append(interests, discovery.ChaincodeInterest{Chaincodes: []discovery.ChaincodeCall{{Name: n}}})\n}","handlingStrategy":"validation","validationCode":"func dropNilInterests(q *discovery.ChaincodeQuery) error {\n    for i, in := range q.Interests {\n        if in == nil {\n            return fmt.Errorf(\"interest at index %d is nil\", i)\n        }\n    }\n    return nil\n}","typeGuard":"func allInterestsNonNil(q *discovery.ChaincodeQuery) bool {\n    for _, in := range q.Interests {\n        if in == nil {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"if err := dropNilInterests(query); err != nil {\n    return fmt.Errorf(\"sanitize interests before sending: %w\", err)\n}\nresp, err := client.Send(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"chaincode interest is nil\") {\n        return fmt.Errorf(\"interests slice contains nil entries; rebuild with append: %w\", err)\n    }\n    return err\n}","preventionTips":["Build slices with append instead of make(..., n) to avoid trailing zero-value/nil entries","Filter nils after any deserialization that can yield null array elements","Unit-test request builders to assert every interest is non-nil via TestValidateCCQuery"],"tags":["discovery","validation","nil-pointer","chaincode","fabric","grpc"],"backgroundTag":"null-required-field","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"}