hyperledger/fabric · error
Tag should be %s
Error message
Tag should be %s
What it means
IsTagLegal requires a data message (IsDataMsg) to carry the CHAN_AND_ORG tag so the message is disseminated only to channel members of the same org. A data message tagged with anything else is rejected with this formatted error naming the expected tag.
Source
Thrown at gossip/protoext/message.go:135
// 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)])
}
return nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Set msg.Tag = gossip.GossipMessage_CHAN_AND_ORG on all data messages before sending.
- Run IsTagLegal on outgoing messages in tests to catch mismatches early.
- If receiving this on the wire, the remote peer is misconfigured/malicious; rely on validateMsg to drop the message.
- Check that the payload type actually is a data message; if not, fix the message construction.
Example fix
// before
m := &gossip.GossipMessage{Content: &gossip.GossipMessage_DataMsg{DataMsg: d}}
// after
m := &gossip.GossipMessage{
Tag: gossip.GossipMessage_CHAN_AND_ORG,
Content: &gossip.GossipMessage_DataMsg{DataMsg: d},
} Defensive patterns
Strategy: validation
Validate before calling
func makeDataMsg(d *gossip.DataMessage) *gossip.GossipMessage {
return &gossip.GossipMessage{
Tag: gossip.GossipMessage_CHAN_AND_ORG,
Content: &gossip.GossipMessage_DataMsg{DataMsg: d},
}
} Type guard
func isLegallyTaggedDataMsg(m *gossip.GossipMessage) bool {
return protoext.IsDataMsg(m) && m.Tag == gossip.GossipMessage_CHAN_AND_ORG
} Try / catch
if err := protoext.IsTagLegal(msg); err != nil {
log.Warningf("illegal data message tag: %v", err)
return
} Prevention
- Use a single factory for data messages that pins Tag = CHAN_AND_ORG.
- Test tag legality whenever message payloads change.
- Drop inbound data messages failing validateMsg at the receiving peer.
- Never copy Tag values between messages of different types.
When it happens
Trigger: Sending/gossiping a GossipMessage that IsDataMsg classifies as a data message (HasDataMsg payload) but whose Tag != GossipMessage_CHAN_AND_ORG; caught by validateMsg on send in the Gossip service or by tests.
Common situations: Hand-crafted DataMsg built with Tag EMPTY, UNDEFINED, or ORG_ONLY; a refactor changed the payload but not the tag; interop with a peer producing malformed data messages.
Related errors
- Undefined tag
- block from orderer could not be re-marshaled: proto: Marshal
- group %s isn't mapped to endorsers, but exists in a layout
- failed creating endorser object
- received empty envelope(s) for endorsers for chaincode %s, c
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9a251ed33bb55480.
Report an issue: GitHub.