hyperledger/fabric · error

not a SmartBFT config block

Error message

not a SmartBFT config block

What it means

IsConsenterOfChannel only validates consenters for channels configured with consensus type BFT (Smart BFT). If the bundle's orderer config reports a different ConsensusType (e.g. etcdraft, solo), the block cannot be interpreted as a SmartBFT config and this error is returned.

Source

Thrown at orderer/consensus/smartbft/util.go:413

// It returns nil if true, else returns an error.
func (conCert ConsenterCertificate) IsConsenterOfChannel(configBlock *cb.Block) error {
	if configBlock == nil {
		return errors.New("nil block")
	}
	envelopeConfig, err := protoutil.ExtractEnvelope(configBlock, 0)
	if err != nil {
		return err
	}
	bundle, err := channelconfig.NewBundleFromEnvelope(envelopeConfig, conCert.CryptoProvider)
	if err != nil {
		return err
	}
	oc, exists := bundle.OrdererConfig()
	if !exists {
		return errors.New("no orderer config in bundle")
	}
	if oc.ConsensusType() != "BFT" {
		return errors.New("not a SmartBFT config block")
	}

	for _, consenter := range oc.Consenters() {
		if bytes.Equal(conCert.ConsenterCertificate, consenter.ServerTlsCert) || bytes.Equal(conCert.ConsenterCertificate, consenter.ClientTlsCert) {
			return nil
		}
	}
	return cluster.ErrNotInChannel
}

type worker struct {
	work      [][]byte
	f         func([]byte)
	workerNum int
	id        int
}

func (w *worker) doWork() {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the channel's consensus.type is set to BFT in configtx.yaml and regenerate/commit the config block
  2. Point IsConsenterOfChannel at a config block belonging to a BFT channel
  3. If the channel should stay etcdraft, use the etcdraft cluster check instead of the SmartBFT one

Example fix

// configtx.yaml
Orderer:
  OrdererType: etcdraft
// after
Orderer:
  OrdererType: BFT
Defensive patterns

Strategy: validation

Validate before calling

bundle, _ := channelconfig.NewBundleFromEnvelope(env, cryptoProvider)
oc, ok := bundle.OrdererConfig()
if ok && oc.ConsensusType() != "BFT" {
    return errors.Errorf("channel consensus is %s, not BFT", oc.ConsensusType())
}

Type guard

func isBFTChannel(oc channelconfig.Orderer) bool {
    return oc.ConsensusType() == "BFT"
}

Try / catch

if err := IsConsenterOfChannel(env, cert); err != nil {
    if strings.Contains(err.Error(), "not a SmartBFT config block") {
        // route to the appropriate consensus-type checker
    }
}

Prevention

When it happens

Trigger: Calling IsConsenterOfChannel on a channel whose orderer group has ConsensusType other than "BFT" — e.g. an etcdraft channel — while the caller expects SmartBFT.

Common situations: Mixed-consensus network where a SmartBFT node receives an etcdraft channel's config block; migrating channels between consensus types but pointing at stale blocks; misconfigured configtx.yaml consensus.type.

Related errors


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