hyperledger/fabric · error

state based endorsement policy cannot be satisfied

Error message

state based endorsement policy cannot be satisfied

What it means

Thrown by computeStateBasedPrincipalSets when a chaincode's state-based (key-level) endorsement policy produced zero comparable principal sets from SatisfiedBy(), i.e. no combination of principals can ever satisfy the policy. Discovery cannot return any peer group that would fulfill this key-level endorsement requirement, so the request is rejected.

Source

Thrown at discovery/endorsement/endorsement.go:239

		if len(chaincode.KeyPolicies) == 0 {
			continue
		}

		logger.Debugf("Chaincode call to %s is satisfied by %d state based policies of %v",
			chaincode.Name, len(chaincode.KeyPolicies), chaincode.KeyPolicies)

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

	if len(stateBasedCPS) > 0 {
		stateBasedPrincipalSet, err := mergePrincipalSets(stateBasedCPS)
		if err != nil {
			return nil, errors.WithStack(err)
		}

		logger.Debugf("Merging state based policies: %v --> %v", stateBasedCPS, stateBasedPrincipalSet)

		return stateBasedPrincipalSet, nil
	}

	logger.Debugf("No state based policies requested")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Review the key-level endorsement policy logic and lower the NOutOf threshold or add principals so it can be satisfied
  2. Ensure all MSPs referenced by the state-based policy exist on the channel (update channel config)
  3. Delete/reset the state-based endorsement policy for the affected keys (unset validation parameter)
  4. If intentionally strict, stop requesting PeersForEndorsement for that chaincode/key combination

Example fix

// before
policy := NOutOf(2, principals(len=1)) // unsatisfiable
// after
policy := NOutOf(1, principals(len=1))
Defensive patterns

Strategy: validation

Validate before calling

policy := inquire.NewInquireableSignaturePolicy(keyPolicy)
if len(policy.SatisfiedBy()) == 0 {
  return errors.New("state-based endorsement policy is unsatisfiable")
}

Type guard

func satisfiable(p *common.SignaturePolicyEnvelope) bool {
  return len(inquire.NewInquireableSignaturePolicy(p).SatisfiedBy()) > 0
}

Try / catch

peers, err := client.PeersForEndorsement(ctx, interest)
if err != nil && strings.Contains(err.Error(), "cannot be satisfied") {
  // inspect/recreate the key-level policy before retrying
}

Prevention

When it happens

Trigger: A KeyPolicy on a chaincode in a ChaincodeInterest inquires to an empty set of satisfying principal combinations — e.g. a signature policy that is logically unsatisfiable (NOutOf threshold exceeding the number of principals, or principals from nonexistent MSPs) or a policy with no satisfying principals.

Common situations: State-based endorsement set with 'OutOf(2, ...)' but only one principal; key-level policies referencing MSP IDs that are not on the channel; policies attached to private data keys whose collections changed.

Related errors


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