hyperledger/fabric · error
Block header is nil
Error message
Block header is nil
What it means
coordinator.StoreBlock requires block.Header to be non-nil because it logs and commits using block.Header.Number. When the header is missing the block cannot be sequenced or validated, so StoreBlock returns this error before any processing.
Solutions
- Re-fetch the block from the orderer/peer to obtain the full block with header
- Check that the block deserialization path (protoutil.UnmarshalBlock / FromBlock) preserved the header
- Fix test or repair code to include a valid Header with BlockNumber
- Inspect the upstream block producer if headers are systematically missing
Example fix
// before
blk, _ := protoutil.UnmarshalBlock(bytes) // partial
c.StoreBlock(blk, pvt)
// after
if blk.Header == nil || blk.Data == nil {
return fmt.Errorf("incomplete block %d", blk.GetHeader().GetNumber())
}
c.StoreBlock(blk, pvt) Defensive patterns
Strategy: type-guard
Validate before calling
if block == nil || block.Header == nil || block.Data == nil {
return errors.New("incomplete block")
} Type guard
func hasHeader(b *common.Block) bool {
return b != nil && b.Header != nil
} Prevention
- Use protoutil.UnmarshalBlock and check it returned the full block
- Never build common.Block by hand without Header in tests
- Re-fetch blocks whose header failed to deserialize
- Log raw bytes of blocks that arrive headerless to trace corruption
When it happens
Trigger: Calling StoreBlock with a common.Block that has Data set but Header nil — typically from a malformed/incomplete deserialization or hand-built block.
Common situations: See trigger scenarios.
Related errors
- Block data is empty
- block data size( ) is different from Tx filter size( )
- Block.Metadata is nil or Block.Metadata lacks a Tx filter…
- commit failed
- failed to commit private data
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/ddc70a54e68892e2.
Report an issue: GitHub.
Appendix: source
Thrown at gossip/privdata/coordinator.go:158
mspID: mspID,
store: store,
selfSignedData: selfSignedData,
transientBlockRetention: config.TransientBlockRetention,
logger: logger.With("channel", support.ChainID),
metrics: metrics,
pullRetryThreshold: config.PullRetryThreshold,
skipPullingInvalidTransactions: config.SkipPullingInvalidTransactions,
idDeserializerFactory: idDeserializerFactory,
}
}
// StoreBlock stores block with private data into the ledger
func (c *coordinator) StoreBlock(block *common.Block, privateDataSets util.PvtDataCollections) error {
if block.Data == nil {
return errors.New("Block data is empty")
}
if block.Header == nil {
return errors.New("Block header is nil")
}
c.logger.Infof("Received block [%d] from buffer", block.Header.Number)
c.logger.Debugf("Validating block [%d]", block.Header.Number)
validationStart := time.Now()
err := c.Validator.Validate(block)
c.reportValidationDuration(time.Since(validationStart))
if err != nil {
c.logger.Errorf("Validation failed: %+v", err)
return err
}
blockAndPvtData := &ledger.BlockAndPvtData{
Block: block,
PvtData: make(ledger.TxPvtDataMap),
MissingPvtData: make(ledger.TxMissingPvtData),View on GitHub (pinned to 2736b63f8f)