hyperledger/fabric · error

received empty envelope(s) for endorsers for chaincode %s, c

Error message

received empty envelope(s) for endorsers for chaincode %s, channel %s

What it means

The endorser() helper requires every peer in an endorsement descriptor to carry both a MembershipInfo (AliveMessage) and a StateInfo envelope. If either is nil, it reports which chaincode and channel the incomplete peer belongs to. Discovery results must contain both envelopes to build a usable Peer object with membership and ledger/state metadata.

Source

Thrown at discovery/client/client.go:533

	for grp, peers := range desc.EndorsersByGroups {
		var endorsers []*Peer
		for _, p := range peers.Peers {
			peer, err := endorser(p, desc.Chaincode, channel)
			if err != nil {
				return nil, errors.Wrap(err, "failed creating endorser object")
			}
			endorsers = append(endorsers, peer)
		}
		descriptor.endorsersByGroups[grp] = endorsers
	}

	return descriptor, nil
}

func endorser(peer *discovery.Peer, chaincode, channel string) (*Peer, error) {
	if peer.MembershipInfo == nil || peer.StateInfo == nil {
		return nil, errors.Errorf("received empty envelope(s) for endorsers for chaincode %s, channel %s", chaincode, channel)
	}
	aliveMsg, err := gprotoext.EnvelopeToGossipMessage(peer.MembershipInfo)
	if err != nil {
		return nil, errors.Wrap(err, "failed unmarshalling gossip envelope to alive message")
	}
	stateInfMsg, err := gprotoext.EnvelopeToGossipMessage(peer.StateInfo)
	if err != nil {
		return nil, errors.Wrap(err, "failed unmarshalling gossip envelope to state info message")
	}
	if err := validateAliveMessage(aliveMsg); err != nil {
		return nil, errors.Wrap(err, "failed validating alive message")
	}
	if err := validateStateInfoMessage(stateInfMsg); err != nil {
		return nil, errors.Wrap(err, "failed validating stateInfo message")
	}
	sID := &msp.SerializedIdentity{}
	if err := proto.Unmarshal(peer.Identity, sID); err != nil {
		return nil, errors.Wrap(err, "failed unmarshalling peer's identity")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Wait for the peer to fully join the channel and gossip StateInfo, then retry the discovery query
  2. Verify all peers listed as endorsers have joined the channel and gossip connectivity (anchor peers)
  3. Check discovery server logs for why StateInfo/MembershipInfo was omitted
  4. Restart or resync gossip on the affected peer if it stays stale
  5. Ensure the query targets the right channel — local membership queries lack StateInfo

Example fix

// defensive: skip incomplete peers client-side before building endorsers
for _, p := range peers.Peers {
	if p.MembershipInfo == nil || p.StateInfo == nil {
		log.Printf("skipping peer with missing envelopes for %s", channel)
		continue
	}
	// ...build endorser
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Skip peers missing envelopes before invoking endorser()
for _, p := range peers.Peers {
	if p.MembershipInfo == nil || p.StateInfo == nil {
		continue
	}
}

Type guard

func hasCompleteEnvelopes(p *discovery.Peer) bool {
	return p != nil && p.MembershipInfo != nil && p.StateInfo != nil
}

Try / catch

peer, err := endorser(p, chaincode, channel)
if err != nil && strings.Contains(err.Error(), "empty envelope") {
	log.Printf("peer %s not ready on %s; retrying", channel, err)
	return retryDiscovery(ctx)
}

Prevention

When it happens

Trigger: A discovery.Peer inside EndorsersByGroups with peer.MembershipInfo == nil or peer.StateInfo == nil while resolving endorsers for a chaincode query on a channel — the server returned the peer but not both gossip envelopes.

Common situations: A peer that recently joined the channel and hasn't published StateInfo; local (non-channel) membership queries mixed with channel queries where StateInfo isn't expected; peers behind network partitions not yet gossiped; discovery cache staleness on the server.

Related errors


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