{"record":{"id":"90cf01df5d479d98","repo":"hyperledger/fabric","slug":"no-principal-sets-remained-after-filtering","errorCode":null,"errorMessage":"no principal sets remained after filtering","messagePattern":"no principal sets remained after filtering","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/endorsement/endorsement.go","lineNumber":690,"sourceCode":"}\n\nfunc mergePrincipalSets(cpss []inquire.ComparablePrincipalSets) (inquire.ComparablePrincipalSets, error) {\n\t// Obtain the first ComparablePrincipalSet first\n\tvar cps inquire.ComparablePrincipalSets\n\tcps, cpss, err := popComparablePrincipalSets(cpss)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\tfor _, cps2 := range cpss {\n\t\tcps = inquire.Merge(cps, cps2)\n\t}\n\treturn cps, nil\n}\n\nfunc popComparablePrincipalSets(sets []inquire.ComparablePrincipalSets) (inquire.ComparablePrincipalSets, []inquire.ComparablePrincipalSets, error) {\n\tif len(sets) == 0 {\n\t\treturn nil, nil, errors.New(\"no principal sets remained after filtering\")\n\t}\n\tcps, cpss := sets[0], sets[1:]\n\treturn cps, cpss, nil\n}\n","sourceCodeStart":672,"sourceCodeEnd":695,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/endorsement/endorsement.go#L672-L695","documentation":"Returned by popComparablePrincipalSets when it is called with an empty slice of ComparablePrincipalSets — internally this happens in mergePrincipalSets after filtering left no candidate principal sets. It signals that after reducing/merging the endorsement (and state-based) principal sets, no valid set remains to recommend peers for endorsement.","triggerScenarios":"mergePrincipalSets iterates the accumulated ComparablePrincipalSets and after removal/filtering passes the remaining slice is empty when popComparablePrincipalSets pops the next set; effectively all candidate principal sets were eliminated during merging (e.g. state-based sets intersected to nothing with namespace sets).","commonSituations":"Combining namespace policy with state-based key policies whose principal requirements are mutually exclusive (e.g. different orgs required by AND); collection policies conflicting with namespace policy so the intersection is empty.","solutions":["Review how the state-based endorsement policy interacts with the namespace policy and align their required principals (same orgs/roles)","Relax the key-level policy (e.g. OR instead of AND across conflicting orgs)","Recommit the chaincode with a consistent endorsement policy so merging retains at least one principal set","If hit programmatically, guard mergePrincipalSets inputs to ensure at least one non-empty ComparablePrincipalSets is passed"],"exampleFix":"// before\nmergePrincipalSets([]inquire.ComparablePrincipalSets{}) // panics/errors\n// after\nif len(sets) == 0 { return nil, errors.New(\"no principal sets remained after filtering\") }","handlingStrategy":"validation","validationCode":"if len(cpss) == 0 { return errors.New(\"no principal sets to merge\") }\nfor _, s := range cpss { if len(s) == 0 { return errors.New(\"empty principal set in merge input\") } }","typeGuard":"func mergeable(sets []inquire.ComparablePrincipalSets) bool {\n  return len(sets) > 0\n}","tryCatchPattern":"peers, err := client.PeersForEndorsement(ctx, interest)\nif err != nil && strings.Contains(err.Error(), \"no principal sets remained after filtering\") {\n  // realign namespace vs state-based policies and retry\n}","preventionTips":["Keep state-based policies consistent with the namespace endorsement policy","Avoid AND-combining policies demanding disjoint orgs","Test policy merging with development channel configs before production"],"tags":["fabric","discovery","principal-sets","policy-merge"],"backgroundTag":"endorsement-policy-unsatisfiable","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"}