hyperledger/fabric · error

failed unmarshalling stateInfo message

Error message

failed unmarshalling stateInfo message

What it means

Same as the alive-message error but for the StateInfo envelope: when the query type requires state info (e.g. chaincode or endorsement queries), the client parses peer.StateInfo into a SignedGossipMessage and wraps any parse failure with this message. The server returned a StateInfo envelope that is nil, truncated, or not a valid gossip message.

Solutions

  1. Confirm the target peers have joined the channel and gossip state info is flowing (peer channel list, gossip logs).
  2. Align client and peer versions/Fabric release.
  3. Retry the discovery request; state info may have been transiently missing.
  4. Validate TLS/network path for corruption.
  5. Fall back to peers that returned valid state info.

Example fix

// before
res, _ := client.SendRequest(ctx, req) // req included chaincode query
// after: catch and retry once against another peer
res, err := client.SendRequest(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed unmarshalling stateInfo message") {
  res, err = client.SendRequest(ctx, reqWithAlternatePeers)
}
Defensive patterns

Strategy: validation

Validate before calling

func hasStateInfo(p *discovery.Peer) bool {
  return p != nil && p.StateInfo != nil && len(p.StateInfo.Payload) > 0
}

Type guard

func isStateInfoMessage(msg *gprotoext.SignedGossipMessage) bool {
  return msg != nil && msg.IsStateInfoMsg()
}

Try / catch

if err != nil {
  if strings.Contains(err.Error(), "failed unmarshalling stateInfo message") {
    return retryDiscovery(ctx, req) // transient: state info may arrive later
  }
  return err
}

Prevention

When it happens

Trigger: A discovery request including a state-info-dependent query (ChaincodeQuery, EndorsementQuery, ConfigQuery paths where isStateInfoExpected(qt) is true) whose response entries contain invalid peer.StateInfo envelopes.

Common situations: Peer that has not yet joined/gossiped state info for the channel; version skew between client and peer protos; corrupted responses from a network middlebox; stale peer membership entries.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at discovery/client/client.go:424

		resp[key] = peers
	}
	return nil
}

func peersForChannel(membersRes *discovery.PeerMembershipResult, qt protoext.QueryType) ([]*Peer, error) {
	var peers []*Peer
	for org, peersOfCurrentOrg := range membersRes.PeersByOrg {
		for _, peer := range peersOfCurrentOrg.Peers {
			aliveMsg, err := gprotoext.EnvelopeToGossipMessage(peer.MembershipInfo)
			if err != nil {
				return nil, errors.Wrap(err, "failed unmarshalling alive message")
			}
			var stateInfoMsg *gprotoext.SignedGossipMessage
			if isStateInfoExpected(qt) {
				stateInfoMsg, err = gprotoext.EnvelopeToGossipMessage(peer.StateInfo)
				if err != nil {
					return nil, errors.Wrap(err, "failed unmarshalling stateInfo message")
				}
				if err := validateStateInfoMessage(stateInfoMsg); err != nil {
					return nil, errors.Wrap(err, "failed validating stateInfo message")
				}
			}
			if err := validateAliveMessage(aliveMsg); err != nil {
				return nil, errors.Wrap(err, "failed validating alive message")
			}
			peers = append(peers, &Peer{
				MSPID:            org,
				Identity:         peer.Identity,
				AliveMessage:     aliveMsg,
				StateInfoMessage: stateInfoMsg,
			})
		}
	}
	return peers, nil
}

View on GitHub (pinned to 2736b63f8f)