hyperledger/fabric · error

Undefined tag

Error message

Undefined tag

What it means

IsTagLegal validates that a GossipMessage's Tag matches its inner message type before the gossip layer sends it. Every GossipMessage must carry a non-UNDEFINED tag; sending with Tag == GossipMessage_UNDEFINED is rejected immediately with this error.

Source

Thrown at gossip/protoext/message.go:131

func IsHelloMsg(m *gossip.GossipMessage) bool {
	return m.GetHello() != nil
}

// IsDigestMsg returns whether this GossipMessage is a digest message
func IsDigestMsg(m *gossip.GossipMessage) bool {
	return m.GetDataDig() != nil
}

// IsLeadershipMsg returns whether this GossipMessage is a leadership (leader election) message
func IsLeadershipMsg(m *gossip.GossipMessage) bool {
	return m.GetLeadershipMsg() != nil
}

// IsTagLegal checks the GossipMessage tags and inner type
// and returns an error if the tag doesn't match the type.
func IsTagLegal(m *gossip.GossipMessage) error {
	if m.Tag == gossip.GossipMessage_UNDEFINED {
		return fmt.Errorf("Undefined tag")
	}
	if IsDataMsg(m) {
		if m.Tag != gossip.GossipMessage_CHAN_AND_ORG {
			return fmt.Errorf("Tag should be %s", gossip.GossipMessage_Tag_name[int32(gossip.GossipMessage_CHAN_AND_ORG)])
		}
		return nil
	}

	if IsAliveMsg(m) || m.GetMemReq() != nil || m.GetMemRes() != nil {
		if m.Tag != gossip.GossipMessage_EMPTY {
			return fmt.Errorf("Tag should be %s", gossip.GossipMessage_Tag_name[int32(gossip.GossipMessage_EMPTY)])
		}
		return nil
	}

	if IsIdentityMsg(m) {
		if m.Tag != gossip.GossipMessage_ORG_ONLY {
			return fmt.Errorf("Tag should be %s", gossip.GossipMessage_Tag_name[int32(gossip.GossipMessage_ORG_ONLY)])

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set the correct Tag for the message type (e.g. CHAN_AND_ORG for data, EMPTY for alive/membership, ORG_ONLY for identity) before sending.
  2. Use protoext's helper constructors/ext wrappers that populate Tag automatically.
  3. If the message came off the wire, validate before use and drop/reject it (that is what validateMsg does).
  4. Add a unit test asserting IsTagLegal(m) == nil for every message your component sends.

Example fix

// before
msg := &gossip.GossipMessage{ Payload: ... }
gossipSvc.Gossip(protoext.NoopSign(msg))
// after
msg := &gossip.GossipMessage{ Tag: gossip.GossipMessage_CHAN_AND_ORG, Payload: ... }
if err := protoext.IsTagLegal(msg); err != nil { return err }
gossipSvc.Gossip(protoext.NoopSign(msg))
Defensive patterns

Strategy: validation

Validate before calling

func validGossipMessage(m *gossip.GossipMessage) bool {
    return m != nil && m.Tag != gossip.GossipMessage_UNDEFINED && protoext.IsTagLegal(m) == nil
}
// guard before send:
if !validGossipMessage(msg) { return errors.New("refusing to send invalid gossip message") }

Type guard

func isTagged(m *gossip.GossipMessage) bool {
    return m != nil && m.Tag != gossip.GossipMessage_UNDEFINED
}

Try / catch

if err := protoext.IsTagLegal(msg); err != nil {
    log.Warningf("dropping message with illegal tag: %v", err)
    return
}

Prevention

When it happens

Trigger: Calling protoext.IsTagLegal (directly or via validateMsg/Gossip send path) with a GossipMessage whose Tag field was left at its zero value GossipMessage_UNDEFINED.

Common situations: Constructing a GossipMessage by hand and forgetting to set Tag; a proto message deserialized from an untrusted/partial source; tests building minimal messages without setting the tag.

Related errors


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