hyperledger/fabric · error

channel %s not found

Error message

channel %s not found

What it means

The Deliver service's policy checker resolves the chain (channel) from the registrar for each deliver request. If s.GetChain(channelID) returns nil — the orderer does not service that channel — the deliver stream is rejected with this error before any signature filtering happens.

Source

Thrown at orderer/common/server/server.go:198

			function: "Broadcast",
		},
	})
}

// Deliver sends a stream of blocks to a client after ordering
func (s *server) Deliver(srv ab.AtomicBroadcast_DeliverServer) error {
	logger.Debugf("Starting new Deliver handler")
	defer func() {
		if r := recover(); r != nil {
			logger.Criticalf("Deliver client triggered panic: %s\n%s", r, debug.Stack())
		}
		logger.Debugf("Closing Deliver stream")
	}()

	policyChecker := func(env *cb.Envelope, channelID string) error {
		chain := s.GetChain(channelID)
		if chain == nil {
			return errors.Errorf("channel %s not found", channelID)
		}
		// In maintenance mode, we typically require the signature of /Channel/Orderer/Readers.
		// This will block Deliver requests from peers (which normally satisfy /Channel/Readers).
		sf := msgprocessor.NewSigFilter(policies.ChannelReaders, policies.ChannelOrdererReaders, chain)
		return sf.Apply(env)
	}
	deliverServer := &deliver.Server{
		PolicyChecker: deliver.PolicyCheckerFunc(policyChecker),
		Receiver: &deliverMsgTracer{
			Receiver: srv,
			msgTracer: msgTracer{
				debug:    s.debug,
				function: "Deliver",
			},
		},
		ResponseSender: &responseSender{
			AtomicBroadcast_DeliverServer: srv,
		},

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Run osnadmin channel list on the orderer and join it to the requested channel with its genesis block
  2. Verify the channel ID the peer uses for deliver matches an existing channel exactly
  3. In a cluster, ensure the channel was created on all intended ordering nodes (consenter set) and they re-joined after restarts

Example fix

// before: deliver to channel without checking membership
chat, _ := server.Deliver(ctx)
chat.Send(seekInfoEnvFor("mychannel"))

// after: verify orderer membership first
channels, _ := osnadmin.ListChannels(ordererURL)
if !channels.Contains("mychannel") {
	osnadmin.JoinChannel(ordererURL, "mychannel", genesisBlockPath)
}
Defensive patterns

Strategy: validation

Validate before calling

// client before opening deliver stream
channels, _ := osnadmin.ListChannels(ordererURL)
if !contains(channels, channelID) {
    return fmt.Errorf("refusing deliver: orderer not joined to %s", channelID)
}

Type guard

func channelExistsOnOrderer(channels []types.ChannelInfo, id string) bool {
    for _, c := range channels {
        if c.Name == id { return true }
    }
    return false
}

Try / catch

resp, err := deliverClient.Send(env)
if err != nil {
    if strings.Contains(err.Error(), "not found") && strings.Contains(err.Error(), channelID) {
        return joinOrdererToChannel(channelID, genesisBlockPath) // then redeliver
    }
    return err
}

Prevention

When it happens

Trigger: A peer or client opening a Deliver/DeliverFiltered stream specifying a channel the orderer hasn't joined, or using the wrong channel name in the seek info envelope.

Common situations: Peer attempting to pull blocks for a channel the ordering node isn't part of; channels created on other orderers in a multi-group cluster; stale channel name in peer config after re-provisioning orderers (participation mode where channels must be re-joined after restart).

Related errors


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