{"record":{"id":"23d71f3b776cc32e","repo":"hyperledger/fabric","slug":"chaincode-interest-is-nil","errorCode":null,"errorMessage":"chaincode interest is nil","messagePattern":"chaincode interest is nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/client/client.go","lineNumber":609,"sourceCode":"\tif si == nil {\n\t\treturn errors.New(\"message isn't a stateInfo message\")\n\t}\n\tif si.Timestamp == nil {\n\t\treturn errors.New(\"timestamp is nil\")\n\t}\n\tif si.Properties == nil {\n\t\treturn errors.New(\"properties is nil\")\n\t}\n\treturn nil\n}\n\nfunc validateInterests(interests ...*peer.ChaincodeInterest) error {\n\tif len(interests) == 0 {\n\t\treturn errors.New(\"no chaincode interests given\")\n\t}\n\tfor _, interest := range interests {\n\t\tif interest == nil {\n\t\t\treturn errors.New(\"chaincode interest is nil\")\n\t\t}\n\t\tif err := InvocationChain(interest.Chaincodes).ValidateInvocationChain(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// InvocationChain aggregates ChaincodeCalls\ntype InvocationChain []*peer.ChaincodeCall\n\n// String returns a string representation of this invocation chain\nfunc (ic InvocationChain) String() string {\n\ts, _ := json.Marshal(ic)\n\treturn string(s)\n}\n\n// ValidateInvocationChain validates the InvocationChain's structure","sourceCodeStart":591,"sourceCodeEnd":627,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/client/client.go#L591-L627","documentation":"validateInterests iterates the provided ChaincodeInterest objects and fails if any individual element is nil. A nil interest cannot describe any chaincode to endorse, so the whole query is rejected before being sent to the discovery service.","triggerScenarios":"Calling discovery.NewEndorsersQuery(i1, nil) or AddEndorsersQuery with a slice that contains a nil *peer.ChaincodeInterest element (e.g. built by appending into a pre-sized slice make([]*peer.ChaincodeInterest, n)).","commonSituations":"Building interests in a loop with make([]..., 0, n) vs make([]..., n) and appending into indexed slots that stay nil; JSON/config parsing leaving optional chaincode entries as nil.","solutions":["Filter nil entries from the interests slice before building the query","Fix slice construction: use append into a zero-length slice instead of pre-sized make","Add an application-level check that every element is non-nil before calling AddEndorsersQuery"],"exampleFix":"// before\ninterests := make([]*peer.ChaincodeInterest, len(chaincodes))\nfor i, cc := range chaincodes {\n    if cc == nil { continue } // leaves nil holes\n    interests[i] = discovery.ChaincodeInterest{...}\n}\nreq := discovery.NewEndorsersQuery(interests...) // panics/validation error\n// after\nvar interests []*peer.ChaincodeInterest\nfor _, cc := range chaincodes {\n    if cc == nil { continue }\n    interests = append(interests, discovery.ChaincodeInterest{Chaincodes: ...})\n}\nif len(interests) == 0 { return errors.New(\"no chaincodes selected\") }\nreq := discovery.NewEndorsersQuery(interests...)","handlingStrategy":"validation","validationCode":"func dropNilInterests(interests []*peer.ChaincodeInterest) []*peer.ChaincodeInterest {\n    out := make([]*peer.ChaincodeInterest, 0, len(interests))\n    for _, i := range interests {\n        if i != nil { out = append(out, i) }\n    }\n    return out\n}","typeGuard":"func allInterestsNonNil(interests []*peer.ChaincodeInterest) bool {\n    for _, i := range interests { if i == nil { return false } }\n    return len(interests) > 0\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"chaincode interest is nil\") {\n    return fmt.Errorf(\"nil entry in interests slice: %w\", err)\n}","preventionTips":["Build slices with append, not pre-sized make with indexed writes","Filter nils before NewEndorsersQuery","Add unit tests for interest-slice construction"],"tags":["hyperledger-fabric","discovery-service","chaincode","nil-check","api-misuse"],"backgroundTag":"nil-argument-validation","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"}