hyperledger/fabric · warning

Empty membership

Error message

Empty membership

What it means

The private data puller fetches missing private data from channel members. After waiting for membership and applying the collection policy filters, if no remaining peer matches any collection policy, there is no one to request data from and fetchPrivateData aborts.

Source

Thrown at gossip/privdata/pull.go:256

func (p *puller) FetchReconciledItems(dig2collectionConfig privdatacommon.Dig2CollectionConfig) (*privdatacommon.FetchedPvtDataContainer, error) {
	// computeFilters returns a map from a digest to a routing filter
	dig2Filter, err := p.computeReconciliationFilters(dig2collectionConfig)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return p.fetchPrivateData(dig2Filter)
}

func (p *puller) fetchPrivateData(dig2Filter digestToFilterMapping) (*privdatacommon.FetchedPvtDataContainer, error) {
	// Get a list of peers per channel
	allFilters := dig2Filter.flattenFilterValues()
	members := p.waitForMembership()
	p.logger.Debug("Total members in channel:", members)
	members = filter.AnyMatch(members, allFilters...)
	p.logger.Debug("Total members that fit some digest:", members)
	if len(members) == 0 {
		p.logger.Warning("Do not know any peer in the channel(", p.channel, ") that matches the policies , aborting")
		return nil, errors.New("Empty membership")
	}
	members = randomizeMemberList(members)
	res := &privdatacommon.FetchedPvtDataContainer{}
	// Distribute requests to peers, and obtain subscriptions for all their messages
	// matchDigestToPeer returns a map from a peer to the digests which we would ask it for
	var peer2digests peer2Digests
	// We expect all private RWSets represented as digests to be collected
	itemsLeftToCollect := len(dig2Filter)
	// As long as we still have some data to collect and new members to ask the data for:
	for itemsLeftToCollect > 0 && len(members) > 0 {
		purgedPvt := p.getPurgedCollections(members, dig2Filter)
		// Need to remove purged digest from mapping
		for _, dig := range purgedPvt {
			res.PurgedElements = append(res.PurgedElements, &protosgossip.PvtDataDigest{
				TxId:       dig.TxId,
				BlockSeq:   dig.BlockSeq,
				SeqInBlock: dig.SeqInBlock,
				Namespace:  dig.Namespace,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Start at least one peer belonging to the collection's member orgs and ensure gossip connects this peer to it
  2. Verify this peer's org is included in the collection's member_orgs_policy if it should have access
  3. Wait for gossip membership convergence after channel join and retry reconciliation
Defensive patterns

Strategy: retry

Validate before calling

if len(gossip.PeersOfChannel(channel)) == 0 {
  // defer fetch until membership exists
}

Try / catch

res, err := puller.Fetch(retryOpts)
if err != nil && strings.Contains(err.Error(), "Empty membership") {
  // retry after gossip membership converges
}

Prevention

When it happens

Trigger: fetch/FetchReconciledItems runs while membership (after AnyMatch with all collection filters) is empty — no peers in the channel view are authorized for any of the missing collections.

Common situations: Peer just joined and gossip membership is empty or not converged; this peer is not a member of any collection (filters exclude everyone it knows); all collection members are offline.

Related errors


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