hyperledger/fabric · error
channel %s doesn't exist
Error message
channel %s doesn't exist
What it means
ApplyFilters looks up the channel's chain support in the registrar's chain map before applying standard message filters. If the named channel is not managed by this orderer, it rejects the envelope with this error. It is the Broadcast-path guard ensuring only channels the orderer participates in accept transactions.
Source
Thrown at orderer/common/multichannel/registrar.go:1016
if payload.Header == nil {
return "", errors.New("missing channel header")
}
chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return "", errors.WithMessage(err, "error unmarshalling channel header")
}
return chdr.ChannelId, nil
}
func (r *Registrar) ApplyFilters(channel string, env *cb.Envelope) error {
r.lock.RLock()
cs, exists := r.chains[channel]
r.lock.RUnlock()
if !exists {
return errors.Errorf("channel %s doesn't exist", channel)
}
return msgprocessor.CreateStandardChannelFilters(cs, r.config).Apply(env)
}
func (r *Registrar) ProposeConfigUpdate(channel string, configtx *cb.Envelope) (*cb.ConfigEnvelope, error) {
r.lock.RLock()
cs, exists := r.chains[channel]
r.lock.RUnlock()
if !exists {
return nil, errors.Errorf("channel %s doesn't exist", channel)
}
return cs.ProposeConfigUpdate(configtx)
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Confirm the channel name in the client matches a channel the orderer has joined (osnadmin channel list)
- Join the orderer to the channel with osnadmin channel join and the channel's genesis block
- Check for typos/case mismatches in the ChannelId used to build the envelope
Example fix
// before: submit to possibly wrong channel
env, _ := protoutil.CreateSignedEnvelope(common.HeaderType_ENDORSER_TRANSACTION, "mychanel", ...)
// after: read the channel name from config, validate first
channel := viper.GetString("channel")
if channel != "mychannel" { return fmt.Errorf("unknown channel %q", channel) }
env, _ := protoutil.CreateSignedEnvelope(common.HeaderType_ENDORSER_TRANSACTION, channel, ...) Defensive patterns
Strategy: validation
Validate before calling
// client: confirm orderer membership before broadcast
resp, _ := osnadmin.ListChannels(ordererURL)
if !contains(resp.Channels, channelID) {
return fmt.Errorf("orderer not joined to channel %s", channelID)
} Type guard
func ordererServesModule(channels []types.ChannelInfo, name string) bool {
for _, c := range channels {
if c.Name == name { return true }
}
return false
} Try / catch
err := broadcast(env)
if err != nil {
if strings.Contains(err.Error(), "doesn't exist") {
// join orderer to the channel, then retry once
_ = osnadmin.Join(ordererURL, channelID, genesisBlockPath)
return broadcast(env)
}
return err
} Prevention
- Centralize channel names in shared config instead of hardcoding literals
- After orderer restarts, script osnadmin channel list/join to restore channel membership
- Match peer and orderer channel sets during environment provisioning
When it happens
Trigger: Broadcasting a transaction envelope to a channel the orderer has not joined (no entry in r.chains) — wrong channel name in the envelope's channel header, or the orderer joined via channel participation but the client targets a different channel.
Common situations: Typo in the channel name in the SDK submit call; peer on channel X while orderer only on channel Y; orderer restarted without re-joining channels when using osnadmin participation (no system channel to auto-load them).
Related errors
- channel does not exist
- channel %s not found
- OrdererOrg config does not allow sub-groups
- Attempted to set the batch size preferred max bytes (%v) gre
- Attempted to set the batch timeout to a invalid value: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/eb0d69d66b0a3649.
Report an issue: GitHub.