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

  1. Confirm the channel name in the client matches a channel the orderer has joined (osnadmin channel list)
  2. Join the orderer to the channel with osnadmin channel join and the channel's genesis block
  3. 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

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


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