{"record":{"id":"a7a4119c6fe1cd8e","repo":"hyperledger/fabric","slug":"received-empty-envelope-s-for-endorsers-for-chain","errorCode":null,"errorMessage":"received empty envelope(s) for endorsers for chaincode %s, channel %s","messagePattern":"received empty envelope\\(s\\) for endorsers for chaincode (.+?), channel (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/client/client.go","lineNumber":533,"sourceCode":"\n\tfor grp, peers := range desc.EndorsersByGroups {\n\t\tvar endorsers []*Peer\n\t\tfor _, p := range peers.Peers {\n\t\t\tpeer, err := endorser(p, desc.Chaincode, channel)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"failed creating endorser object\")\n\t\t\t}\n\t\t\tendorsers = append(endorsers, peer)\n\t\t}\n\t\tdescriptor.endorsersByGroups[grp] = endorsers\n\t}\n\n\treturn descriptor, nil\n}\n\nfunc endorser(peer *discovery.Peer, chaincode, channel string) (*Peer, error) {\n\tif peer.MembershipInfo == nil || peer.StateInfo == nil {\n\t\treturn nil, errors.Errorf(\"received empty envelope(s) for endorsers for chaincode %s, channel %s\", chaincode, channel)\n\t}\n\taliveMsg, err := gprotoext.EnvelopeToGossipMessage(peer.MembershipInfo)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshalling gossip envelope to alive message\")\n\t}\n\tstateInfMsg, err := gprotoext.EnvelopeToGossipMessage(peer.StateInfo)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshalling gossip envelope to state info message\")\n\t}\n\tif err := validateAliveMessage(aliveMsg); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed validating alive message\")\n\t}\n\tif err := validateStateInfoMessage(stateInfMsg); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed validating stateInfo message\")\n\t}\n\tsID := &msp.SerializedIdentity{}\n\tif err := proto.Unmarshal(peer.Identity, sID); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshalling peer's identity\")","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/client/client.go#L515-L551","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for the peer to fully join the channel and gossip StateInfo, then retry the discovery query","Verify all peers listed as endorsers have joined the channel and gossip connectivity (anchor peers)","Check discovery server logs for why StateInfo/MembershipInfo was omitted","Restart or resync gossip on the affected peer if it stays stale","Ensure the query targets the right channel — local membership queries lack StateInfo"],"exampleFix":"// defensive: skip incomplete peers client-side before building endorsers\nfor _, p := range peers.Peers {\n\tif p.MembershipInfo == nil || p.StateInfo == nil {\n\t\tlog.Printf(\"skipping peer with missing envelopes for %s\", channel)\n\t\tcontinue\n\t}\n\t// ...build endorser\n}","handlingStrategy":"type-guard","validationCode":"// Skip peers missing envelopes before invoking endorser()\nfor _, p := range peers.Peers {\n\tif p.MembershipInfo == nil || p.StateInfo == nil {\n\t\tcontinue\n\t}\n}","typeGuard":"func hasCompleteEnvelopes(p *discovery.Peer) bool {\n\treturn p != nil && p.MembershipInfo != nil && p.StateInfo != nil\n}","tryCatchPattern":"peer, err := endorser(p, chaincode, channel)\nif err != nil && strings.Contains(err.Error(), \"empty envelope\") {\n\tlog.Printf(\"peer %s not ready on %s; retrying\", channel, err)\n\treturn retryDiscovery(ctx)\n}","preventionTips":["Query channels, not local membership, when StateInfo is needed","Wait for peers to finish joining before discovery calls","Check gossip connectivity (anchor peers) for all endorsing orgs","Retry on transient empty envelopes"],"tags":["hyperledger-fabric","discovery-service","gossip","stateinfo"],"backgroundTag":"missing-gossip-envelope","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}