hyperledger/fabric · error

no peer combination can satisfy the endorsement policy

Error message

no peer combination can satisfy the endorsement policy

What it means

Discovery computes layouts: combinations of peer groups that jointly satisfy the chaincode's endorsement policy principals. If computeLayouts cannot produce any combination from the current alive membership that satisfies the policy, no valid endorsement is possible from the visible network and this error is returned in the EndorsementDescriptor.

Source

Thrown at discovery/endorsement/endorsement.go:173

	identitiesOfMembers memberIdentities
	chaincodeMapping    map[string]gossipdiscovery.NetworkMember
}

func (ea *endorsementAnalyzer) computeEndorsementResponse(ctx *context) (*discovery.EndorsementDescriptor, error) {
	// mapPrincipalsToGroups returns a mapping from principals to their corresponding groups.
	// groups are just human readable representations that mask the principals behind them
	principalGroups := mapPrincipalsToGroups(ctx.principalsSets)
	// principalsToPeersGraph computes a bipartite graph (V1 U V2 , E)
	// such that V1 is the peers, V2 are the principals,
	// and each e=(peer,principal) is in E if the peer satisfies the principal
	satGraph := principalsToPeersGraph(principalAndPeerData{
		members: ctx.aliveMembership,
		pGrps:   principalGroups,
	}, ea.satisfiesPrincipal(ctx.channel, ctx.identitiesOfMembers))

	layouts := computeLayouts(ctx.principalsSets, principalGroups, satGraph)
	if len(layouts) == 0 {
		return nil, errors.New("no peer combination can satisfy the endorsement policy")
	}

	criteria := &peerMembershipCriteria{
		possibleLayouts:  layouts,
		satGraph:         satGraph,
		chanMemberById:   ctx.channelMembersById,
		idOfMembers:      ctx.identitiesOfMembers,
		chaincodeMapping: ctx.chaincodeMapping,
	}

	groupToEndorserListMapping := endorsersByGroup(criteria)
	layouts = filterOutUnsatisfiedLayouts(groupToEndorserListMapping, layouts)

	if len(layouts) == 0 {
		return nil, errors.New("required chaincodes are not installed on sufficient peers")
	}

	return &discovery.EndorsementDescriptor{

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure at least one peer of every organization required by the policy is running and joined to the channel
  2. Revise the endorsement policy (e.g. OR('Org1MSP.peer','Org2MSP.peer')) to match actual channel membership
  3. Check gossip connectivity so the peer's aliveMembership view includes the needed peers
  4. Re-request discovery after peers recover
Defensive patterns

Strategy: fallback

Validate before calling

// verify required orgs have alive peers before discovery
for _, org := range policyOrgs {
    if !peerDiscoveryReportsAlivePeer(org) {
        return fmt.Errorf("org %s has no alive peers; policy cannot be satisfied", org)
    }
}

Try / catch

desc, err := client.PeersForEndorsement(req)
if err != nil {
    if strings.Contains(err.Error(), "no peer combination") {
        // fall back to static endorsement peers from connection profile
        return staticEndorsers, nil
    }
    return nil, err
}

Prevention

When it happens

Trigger: Endorsement policy requires organizations whose peers are all down/not in gossip membership; policy principals (e.g. OR of MSP roles) that no alive peer satisfies; channel membership too small for the policy.

Common situations: Partners' peers offline so cross-org policies can't be satisfied; peer joined to channel lacking required orgs; endorsement policy updated to require an org not on the channel; gossip bootstrap issues leaving local peer's view incomplete.

Related errors


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