hyperledger/fabric · error

requested to Send for channel %s, but no such channel exists

Error message

requested to Send for channel %s, but no such channel exists

What it means

SendByCriteria resolves the target channel via chanState.getGossipChannelByChainID when criteria.Channel is set. If no gossip channel was joined for that chain ID, membership cannot be scoped, so the send is rejected with this error rather than broadcasting blindly.

Source

Thrown at gossip/gossip/gossip_impl.go:643

// SendByCriteria sends a given message to all peers that match the given SendCriteria
func (g *Node) SendByCriteria(msg *protoext.SignedGossipMessage, criteria SendCriteria) error {
	if criteria.MaxPeers == 0 {
		return nil
	}
	if criteria.Timeout == 0 {
		return errors.New("Timeout should be specified")
	}

	if criteria.IsEligible == nil {
		criteria.IsEligible = filter.SelectAllPolicy
	}

	membership := g.disc.GetMembership()

	if len(criteria.Channel) > 0 {
		gc := g.chanState.getGossipChannelByChainID(criteria.Channel)
		if gc == nil {
			return fmt.Errorf("requested to Send for channel %s, but no such channel exists", criteria.Channel)
		}
		membership = gc.GetPeers()
	}

	peers2send := filter.SelectPeers(criteria.MaxPeers, membership, criteria.IsEligible)
	if len(peers2send) < criteria.MinAck {
		return fmt.Errorf("requested to send to at least %d peers, but know only of %d suitable peers", criteria.MinAck, len(peers2send))
	}

	results := g.comm.SendWithAck(msg, criteria.Timeout, criteria.MinAck, peers2send...)

	for _, res := range results {
		if res.Error() == "" {
			continue
		}
		g.logger.Warning("Failed sending to", res.Endpoint, "error:", res.Error())
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Call JoinChan (or ensure the peer actually joined) for the target channel before sending
  2. Verify the exact channel ID bytes match the channel's name (channel is a []byte compared by value)
  3. Check the peer's gossip membership/state to confirm the channel exists before issuing the send

Example fix

// before
g.SendByCriteria(msg, SendCriteria{Channel: []byte("my-channel"), Timeout: time.Second, MaxPeers: 2})

// after
if g.chanState.getGossipChannelByChainID([]byte("my-channel")) == nil {
    g.JoinChan(joinMsg, common.ChainID("my-channel"))
}
g.SendByCriteria(msg, SendCriteria{Channel: []byte("my-channel"), Timeout: time.Second, MaxPeers: 2})
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the channel exists before sending
if gc := g.chanState.getGossipChannelByChainID(criteria.Channel); gc == nil {
    return fmt.Errorf("cannot send: not joined to channel %s", criteria.Channel)
}
err := g.SendByCriteria(msg, criteria)

Try / catch

if err := g.SendByCriteria(msg, criteria); err != nil && strings.Contains(err.Error(), "no such channel exists") {
    logger.Warningf("skipping send, not a member of %s", criteria.Channel)
    return
}

Prevention

When it happens

Trigger: Calling SendByCriteria with criteria.Channel set to a channel name the node never joined (JoinChan not called), a misspelled chain ID, or a channel the node left/stopped before the send.

Common situations: Sending messages to peers on a newly created channel before the local node's gossip service joined it; byte-slice channel names compared by exact bytes so typos or wrong encoding slip through; channel removed by config change while a sender still targets it.

Related errors


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