hyperledger/fabric · error
nil block
Error message
nil block
What it means
ConfigEnvelopeFromBlock returns this error when called with a nil *common.Block. It is a defensive guard: no envelope can be extracted from a nonexistent block, so the function fails fast with a plain sentinel error.
Source
Thrown at orderer/consensus/etcdraft/util.go:153
func ConfigChannelHeader(block *common.Block) (hdr *common.ChannelHeader, err error) {
envelope, err := protoutil.ExtractEnvelope(block, 0)
if err != nil {
return nil, errors.Wrap(err, "failed to extract envelope from the block")
}
channelHeader, err := protoutil.ChannelHeader(envelope)
if err != nil {
return nil, errors.Wrap(err, "cannot extract channel header")
}
return channelHeader, nil
}
// ConfigEnvelopeFromBlock extracts configuration envelope from the block based on the
// config type, i.e. HeaderType_ORDERER_TRANSACTION or HeaderType_CONFIG
func ConfigEnvelopeFromBlock(block *common.Block) (*common.Envelope, error) {
if block == nil {
return nil, errors.New("nil block")
}
envelope, err := protoutil.ExtractEnvelope(block, 0)
if err != nil {
return nil, errors.Wrapf(err, "failed to extract envelope from the block")
}
channelHeader, err := protoutil.ChannelHeader(envelope)
if err != nil {
return nil, errors.Wrap(err, "cannot extract channel header")
}
switch channelHeader.GetType() {
case int32(common.HeaderType_ORDERER_TRANSACTION):
return nil, errors.Errorf("unsupported legacy system channel header type: %v", channelHeader.GetType())
case int32(common.HeaderType_CONFIG):
return envelope, nil
default:View on GitHub (pinned to 2736b63f8f)
Solutions
- Check for nil before calling: only invoke ConsensusMetadataFromConfigBlock / ConfigEnvelopeFromBlock with a block confirmed non-nil.
- Fix the upstream block-retrieval path so a missing block is surfaced as an error instead of (nil, nil).
- In tests, ensure block fixtures are actually assigned before use.
Example fix
// before
block, _ := ledger.GetBlockByNumber(5) // may be nil
meta, _, err := ConsensusMetadataFromConfigBlock(block)
// after
block, err := ledger.GetBlockByNumber(5)
if err != nil {
return err
}
if block == nil {
return errors.New("block 5 not found in ledger")
}
meta, _, err := ConsensusMetadataFromConfigBlock(block) Defensive patterns
Strategy: type-guard
Validate before calling
if block == nil {
return errors.New("config block is nil")
} Type guard
func nonNilBlock(block *common.Block) bool {
return block != nil && block.Header != nil && block.Data != nil
} Try / catch
envelope, err := ConfigEnvelopeFromBlock(block)
if err != nil {
if err.Error() == "nil block" {
return errors.New("block retrieval returned nothing")
}
return err
} Prevention
- Never ignore the error return of block-lookup APIs (avoid `block, _ :=`).
- Treat a nil block result from the ledger as an explicit 'not found' error.
- Initialize test fixtures before use; assert non-nil in test setup.
When it happens
Trigger: Passing a nil block into ConfigEnvelopeFromBlock, usually indirectly via ConsensusMetadataFromConfigBlock when the caller obtained a nil block (e.g. a failed GetBlockById/RetrieveBlock returned nil without an error).
Common situations: Ledger/block retrieval returning (nil, nil); chain puller logic handing through a missing block; ordering system channel removal flows reading a block that was never written.
Related errors
- cannot extract channel header
- unexpected header type: %v
- failed to extract payload from config envelope
- nil block or nil header
- cannot load client cert for consenter %s:%d: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/41acb263dc3961b5.
Report an issue: GitHub.