hyperledger/fabric · error

nil block or nil header

Error message

nil block or nil header

What it means

ConsenterCertificate.IsConsenterOfChannel checks whether this consenter's certificate appears in a channel's orderer config by inspecting a config block. It throws errors.New("nil block or nil header") when the caller passes a configBlock that is nil or whose block header is nil, i.e. there is no usable block to inspect. It is a defensive precondition check before ExtractEnvelope.

Source

Thrown at orderer/consensus/etcdraft/util.go:363

		return err
	}

	return nil
}

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

// 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 *common.Block) error {
	if configBlock == nil || configBlock.GetHeader() == nil {
		return errors.New("nil block or nil header")
	}
	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")
	}
	m := &etcdraft.ConfigMetadata{}
	if err := proto.Unmarshal(oc.ConsensusMetadata(), m); err != nil {
		return err
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure a valid config block is loaded (from genesis file or ledger) before calling IsConsenterOfChannel
  2. Check configBlock != nil && configBlock.GetHeader() != nil at the call site before invoking
  3. Fix the bootstrap path so the genesis block is correctly read/decoded (correct file path, ORDERER_GENERAL_GENESISMETHOD etc.)

Example fix

// before
err := conCert.IsConsenterOfChannel(nil)
// after
configBlock := retrieveConfigBlock(ledger)
if configBlock == nil || configBlock.GetHeader() == nil {
    return errors.New("config block not available")
}
err := conCert.IsConsenterOfChannel(configBlock)
Defensive patterns

Strategy: type-guard

Validate before calling

if configBlock == nil || configBlock.GetHeader() == nil {
    return errors.New("valid config block required")
}

Type guard

func isValidBlock(b *common.Block) bool {
    return b != nil && b.GetHeader() != nil
}

Prevention

When it happens

Trigger: Calling IsConsenterOfChannel (e.g. during etcdraft chain start / cluster membership check) with a configBlock variable that was never populated or a zero-value common.Block whose Header was never set.

Common situations: Orderer startup before the genesis/config block was retrieved from the ledger or file; passing the result of a failed config-block lookup without checking for nil; unit tests constructing an empty &common.Block{}.

Related errors


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