hyperledger/fabric · error
signature policy is not an OR concatenation, NOutOf %d
Error message
signature policy is not an OR concatenation, NOutOf %d
What it means
Collection member orgs policies must be a flat OR concatenation of principals: every NOutOf rule must have N == 1 (an OR). This error is thrown when validateSpOrConcat encounters an NOutOf rule whose N is not 1, meaning the policy requires multiple principals jointly rather than any-one-of them.
Source
Thrown at core/chaincode/lifecycle/scc.go:908
if _, err := mspMgr.DeserializeIdentity(principal.Principal); err != nil {
return errors.Errorf("collection-name: %s -- contains an identity that is not part of the channel", coll.GetName())
}
default:
return errors.Errorf("collection-name: %s -- principal type %v is not supported", coll.GetName(), principal.PrincipalClassification)
}
}
return nil
}
// validateSpOrConcat checks if the supplied signature policy is just an OR-concatenation of identities
func validateSpOrConcat(sp *common.SignaturePolicy) error {
if sp.GetNOutOf() == nil {
return nil
}
// check if N == 1 (OR concatenation)
if sp.GetNOutOf().N != 1 {
return errors.Errorf("signature policy is not an OR concatenation, NOutOf %d", sp.GetNOutOf().N)
}
// recurse into all sub-rules
for _, rule := range sp.GetNOutOf().Rules {
err := validateSpOrConcat(rule)
if err != nil {
return err
}
}
return nil
}
func validateCollConfigsAgainstCommittedDef(
proposedCollConfs []*pb.StaticCollectionConfig,
committedCollConfPkg *pb.CollectionConfigPackage,
) error {
if committedCollConfPkg == nil || len(committedCollConfPkg.Config) == 0 {
return nil
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Rewrite the policy so all branches are NOutOf with N=1 (pure OR of principals).
- Express per-org requirements as separate principals in the OR list rather than AND-combining them.
- If AND semantics are required, move that requirement into chaincode-level checks, not the collection policy.
- Use a policy builder that produces OR-of-identities for collections.
Example fix
// before: AND of two orgs (N=2)
nOutOf := &common.SignaturePolicy_NOutOf{N: 2, Rules: rulesOfOrg1AndOrg2}
// after: OR of both orgs (N=1)
nOutOf := &common.SignaturePolicy_NOutOf{N: 1, Rules: []*common.SignaturePolicy{org1Member, org2Member}} Defensive patterns
Strategy: validation
Validate before calling
func assertORConcat(sp *common.SignaturePolicy) error {
if sp.GetNOutOf() == nil { return nil }
if sp.GetNOutOf().N != 1 { return fmt.Errorf("NOutOf %d not allowed in collection policy", sp.GetNOutOf().N) }
for _, r := range sp.GetNOutOf().Rules {
if err := assertORConcat(r); err != nil { return err }
}
return nil
} Type guard
func isORConcat(sp *common.SignaturePolicy) bool {
if sp.GetNOutOf() == nil { return true }
if sp.GetNOutOf().N != 1 { return false }
for _, r := range sp.GetNOutOf().Rules {
if !isORConcat(r) { return false }
}
return true
} Try / catch
if err := approve(...); err != nil {
if strings.Contains(err.Error(), "signature policy is not an OR concatenation") {
// rewrite policy as OR of principals (N=1) and resubmit
}
return err
} Prevention
- Never set N > 1 in NOutOf rules of a collection member orgs policy.
- Do not copy endorsement policies into collection configs.
- Add assertORConcat to pre-submission validation of collection configs.
When it happens
Trigger: A collection config member_orgs_policy signature policy containing NOutOf with N >= 2 (e.g. AND of two orgs or a 2-of-3 rule), during collection config validation.
Common situations: Copying a chaincode endorsement policy (which allows M-of-N) into a collection member orgs policy; expressing 'both orgs must agree' requirements in private data distribution, which fabric does not support.
Related errors
- collection-name: %s -- cannot unmarshal identity bytes into
- collection-name: %s -- collection member '%s' is not part of
- collection-name: %s -- cannot unmarshal identity bytes into
- collection-name: %s -- principal type %v is not supported
- the proposed collection config does not contain previously d
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/20d1218eb3562d01.
Report an issue: GitHub.