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.
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)
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
- commit failed
- Block.Metadata is nil or Block.Metadata lacks a Tx filter bi
- block data size(%d) is different from Tx filter size(%d)
- invalid key [%s], cannot begin with "_"
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/ddc70a54e68892e2.
Report an issue: GitHub.