hyperledger/fabric · warning

nil block

Error message

nil block

What it means

ConsenterCertificate.IsConsenterOfChannel inspects a configuration block to decide whether this node's certificate belongs to the channel's consenter set. It explicitly rejects a nil configBlock with this sentinel error, because membership cannot be determined without configuration. Callers typically treat a non-nil return (including this one) as 'not a consenter of the channel'.

Source

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

type nodeConfig struct {
	id2Identities NodeIdentitiesByID
	remoteNodes   []cluster.RemoteNode
	nodeIDs       []uint64
	consenters    []*cb.Consenter
}

// ConsenterCertificate denotes a TLS certificate of a consenter
type ConsenterCertificate struct {
	ConsenterCertificate []byte
	CryptoProvider       bccsp.BCCSP
}

// IsConsenterOfChannel returns whether the caller is a consenter of a channel
// by inspecting the given configuration block.
// 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() {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the channel name/ID used to look up the config block is correct and the channel actually exists on this orderer
  2. Ensure the ledger for the channel contains at least the genesis/config block; if not, fetch/join the channel or create it
  3. Check for storage corruption or an uninitialized fileLedger directory for that channel and re-initialize from a healthy node
  4. At the call site, treat this error as 'not a consenter of this channel' and skip, as designed by the function contract

Example fix

// before
var configBlock *cb.Block
err := conCert.IsConsenterOfChannel(configBlock) // panic-prone/nil sentinel

// after
classifier := mgr.GetChain(chainID)
configBlock := ledger(configID).GetConfigBlock() // ensure non-nil via ledger lookup
if configBlock == nil {
    return nil // not a consenter; no config exists yet
}
err := conCert.IsConsenterOfChannel(configBlock)
Defensive patterns

Strategy: type-guard

Validate before calling

configBlock := ledgerInstance.GetConfigBlock(chainID)
if configBlock == nil {
    // channel has no config yet; skip consenter check instead of calling IsConsenterOfChannel
    return nil
}

Type guard

func hasConfigBlock(block *cb.Block) bool {
    return block != nil && block.Header != nil && len(block.Data.GetData()) > 0
}

// usage:
// if !hasConfigBlock(configBlock) { /* not a consenter / channel not initialized */ }

Try / catch

if err := conCert.IsConsenterOfChannel(configBlock); err != nil {
    if err.Error() == "nil block" {
        // no config available for this channel; treat as not-a-consenter and continue chain selection
        return
    }
    // other errors: envelope extraction / bundle failures — log for diagnosis
    logger.Warnf("consenter channel check failed: %v", err)
}

Prevention

When it happens

Trigger: IsConsenterOfChannel(nil) — called (e.g. from orderer chain-selection / server code) when no config block was found for the chain, such as an empty ledger, chain not yet started, or lookup returning nil for the channel's latest config block.

Common situations: Orderer asked to serve/validate a channel whose ledger has no blocks yet; channel name typo so no config block is retrievable; ledger storage empty or not initialized for that channelID; startup ordering where the chain manager queries before the genesis block is written.

Related errors


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