hyperledger/fabric · error
block must be different from nil, channel=%s
Error message
block must be different from nil, channel=%s
What it means
verifyHeader is the first check in block chain verification: a nil block cannot be verified against the expected sequence number (lastBlockHeader.Number + 1), so it is rejected immediately with the channel name in the message.
Source
Thrown at common/deliverclient/block_verification.go:313
// UpdateBlockHeader saves the last block header that was verified and handled successfully.
// This must be called after VerifyBlock and VerifyBlockAttestation and successfully handling the block.
func (a *BlockVerificationAssistant) UpdateBlockHeader(block *common.Block) {
a.lastBlockHeader = block.Header
a.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)
}
func (a *BlockVerificationAssistant) verifyMetadata(block *common.Block) error {
if block.Metadata == nil || len(block.Metadata.Metadata) < len(common.BlockMetadataIndex_name) {
return errors.Errorf("block with id [%d] on channel [%s] does not have metadata or contains too few entries", block.Header.Number, a.channelID)
}
return nil
}
func (a *BlockVerificationAssistant) verifyHeader(block *common.Block) error {
if block == nil {
return errors.Errorf("block must be different from nil, channel=%s", a.channelID)
}
if block.Header == nil {
return errors.Errorf("invalid block, header must be different from nil, channel=%s", a.channelID)
}
expectedBlockNum := a.lastBlockHeader.Number + 1
if expectedBlockNum != block.Header.Number {
return errors.Errorf("expected block number is [%d] but actual block number inside block is [%d]", expectedBlockNum, block.Header.Number)
}
if len(a.lastBlockHeaderHash) != 0 {
if !bytes.Equal(block.Header.PreviousHash, a.lastBlockHeaderHash) {
return errors.Errorf("Header.PreviousHash of block [%d] is different from Hash(block.Header) of previous block, on channel [%s], received: %s, expected: %s",
block.Header.Number, a.channelID, hex.EncodeToString(block.Header.PreviousHash), hex.EncodeToString(a.lastBlockHeaderHash))
}
}
return nil
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Guard the caller: check block != nil (and block.Header != nil) before calling VerifyBlock/VerifyBlockAttestation.
- Check why the deliver stream produced a nil block — inspect the received DeliverResponse/Envelope unmarshalling errors.
- Log the delivery response error instead of discarding it before invoking verification.
Example fix
// before
if err := bva.VerifyBlock(recvBlock, cryptoOpts); err != nil {...}
// after
if recvBlock == nil || recvBlock.Header == nil {
return fmt.Errorf("no block received from orderer")
}
if err := bva.VerifyBlock(recvBlock, cryptoOpts); err != nil {...} Defensive patterns
Strategy: type-guard
Validate before calling
if block == nil || block.Header == nil {
return errors.New("deliver response contained no block")
} Type guard
func isVerifiableBlock(block *common.Block) bool {
return block != nil && block.Header != nil
} Try / catch
resp, err := deliverStream.Recv()
if err != nil { return err }
block, err := protoutil.UnmarshalBlock(resp.GetBlock())
if err != nil || block == nil { return fmt.Errorf("failed to decode delivered block: %w", err) }
return bva.VerifyBlock(block, opts) Prevention
- Always check deliver stream errors before using the returned block
- Unmarshal delivered envelopes with protoutil.UnmarshalBlock and propagate its error
- Never pass through nil from mocks/helpers without explicit failure handling
When it happens
Trigger: VerifyBlock or VerifyBlockAttestation invoked with a nil *common.Block — typically a deliver client callback received a nil block (failed unmarshalling of the delivered message, or a placeholder nil passed in custom code).
Common situations: Custom deliver handlers passing the block variable without checking it after a failed/unsuccessful delivery; mocks in tests returning nil; a nil result from a decode helper silently propagated.
Related errors
- last block header hash is missing
- missing channel header
- config block channel ID [%s] does not match expected: [%s]
- Invalid signed proposal during check policy on channel [%s]
- proto: Marshal called with nil
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/952df06436045947.
Report an issue: GitHub.