{"record":{"id":"909ad76cd7019c5b","repo":"hyperledger/fabric","slug":"invocation-chain-should-not-be-empty","errorCode":null,"errorMessage":"invocation chain should not be empty","messagePattern":"invocation chain should not be empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/client/client.go","lineNumber":630,"sourceCode":"\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\nfunc (ic InvocationChain) ValidateInvocationChain() error {\n\tif len(ic) == 0 {\n\t\treturn errors.New(\"invocation chain should not be empty\")\n\t}\n\tfor _, cc := range ic {\n\t\tif cc.Name == \"\" {\n\t\t\treturn errors.New(\"chaincode name should not be empty\")\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":612,"sourceCodeEnd":639,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/client/client.go#L612-L639","documentation":"ValidateInvocationChain on the discovery client's InvocationChain type checks structural validity before the chain is used to build endorsement queries. If the slice itself is empty (no chaincode calls were appended), there is nothing to query the discovery service about, so the library rejects it upfront with this error. It is a fail-fast guard against sending a meaningless request to the peer's discovery service.","triggerScenarios":"Calling InvocationChain.ValidateInvocationChain() on an InvocationChain that was never populated — e.g. `var chain discovery.InvocationChain; chain.ValidateInvocationChain()` or `discovery.InvocationChain{}.ValidateInvocationChain()`.","commonSituations":"Building endorsement-selection code where chaincode calls are appended conditionally and all branches were skipped; refactoring that dropped the Append call; loading chaincode lists from empty config or CLI flag slices.","solutions":["Append at least one ChaincodeCall to the InvocationChain (e.g. chain = chain.Append(discovery.ChaincodeCall{Name: \"mycc\"})) before validating","Check that the slice/flags feeding the chain construction actually contain entries","Skip the explicit ValidateInvocationChain call only if you construct the chain via the client API which enforces non-empty input"],"exampleFix":"// before\nvar chain discovery.InvocationChain\nerr := chain.ValidateInvocationChain()\n// after\nchain := discovery.NewInvocationChain(\"mycc\", discovery.ChaincodeCall{Name: \"mycc\"})\nerr := chain.ValidateInvocationChain()","handlingStrategy":"validation","validationCode":"if len(chain) == 0 {\n    return errors.New(\"refusing to query discovery: invocation chain is empty\")\n}\nfor _, cc := range chain {\n    if cc.Name == \"\" {\n        return fmt.Errorf(\"invocation chain entry %q has empty name\", cc)\n    }\n}","typeGuard":"func chainIsValid(chain discovery.InvocationChain) bool {\n    return len(chain) > 0\n}","tryCatchPattern":"if err := chain.ValidateInvocationChain(); err != nil {\n    log.Printf(\"invalid invocation chain: %v\", err)\n    return err\n}","preventionTips":["Always build the chain via Append/NewInvocationChain helpers instead of raw literals","Validate config-sourced chaincode lists before constructing the chain","Unit-test chain construction for empty-input paths"],"tags":["go","discovery","validation","input-validation"],"backgroundTag":"empty-collection-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"}