hyperledger/fabric · error

endorsement policy cannot be satisfied

Error message

endorsement policy cannot be satisfied

What it means

Thrown by computePrincipalSets when a chaincode or collection endorsement policy inquires (SatisfiedBy) to zero comparable principal sets — meaning no principal combination can satisfy it. Discovery therefore cannot propose any peer group for endorsement and rejects the query.

Source

Thrown at discovery/endorsement/endorsement.go:302

				" however there exist %d collection policies taken into account", chaincode.Name, len(policies)-1)
			policies = policies[1:]
		}
		inquireablePoliciesForChaincodeAndCollections = append(inquireablePoliciesForChaincodeAndCollections, policies...)
	}

	var cpss []inquire.ComparablePrincipalSets

	for _, policy := range inquireablePoliciesForChaincodeAndCollections {
		var cmpsets inquire.ComparablePrincipalSets
		for _, ps := range policy.SatisfiedBy() {
			cps := inquire.NewComparablePrincipalSet(ps)
			if cps == nil {
				return nil, errors.New("failed creating a comparable principal set")
			}
			cmpsets = append(cmpsets, cps)
		}
		if len(cmpsets) == 0 {
			return nil, errors.New("endorsement policy cannot be satisfied")
		}
		cpss = append(cpss, cmpsets)
	}

	stateBasedCPS, err := computeStateBasedPrincipalSets(interest.Chaincodes, sessionLogger)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	if len(stateBasedCPS) > 0 {
		cpss = append(cpss, stateBasedCPS)
	}

	cps, err := mergePrincipalSets(cpss)
	if err != nil {
		return nil, errors.WithStack(err)
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Lower the NOutOf threshold or add principals so the policy can be satisfied by existing channel members
  2. Verify all MSPs referenced by the policy are configured on the channel (channel config update if needed)
  3. Re-commit or update the chaincode/collection endorsement policy with a satisfiable definition
  4. Check the policy for typo'd MSP IDs using peer chaincode querycommitted / policy inspection

Example fix

// before
policy := "OUTOF(3, 'Org1MSP.peer', 'Org2MSP.peer')" // needs 3 of 2
// after
policy := "OUTOF(2, 'Org1MSP.peer', 'Org2MSP.peer')"
Defensive patterns

Strategy: validation

Validate before calling

satisfactions := policy.SatisfiedBy()
if len(satisfactions) == 0 { return errors.New("endorsement policy cannot be satisfied by any channel principal") }

Type guard

func anySatisfyingCombination(p policies.InquireablePolicy) bool {
  return len(p.SatisfiedBy()) > 0
}

Try / catch

peers, err := client.PeersForEndorsement(ctx, interest)
if err != nil && strings.Contains(err.Error(), "endorsement policy cannot be satisfied") {
  // fix threshold/principals in the committed policy before retry
}

Prevention

When it happens

Trigger: A committed endorsement policy (namespace or collection) that is logically unsatisfiable: NOutOf threshold higher than the number of sub-policies, references to MSPs absent from the channel, or an empty principal set after inquiry.

Common situations: Policies like OUTOF(3, Org1, Org2) with two orgs; org removed from channel after chaincode commit; collection policies requiring principals from MSPs not on the channel; typo'd MSP IDs in the policy string.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/9f6283a916340c8a. Report an issue: GitHub.