hyperledger/fabric · error
empty block data
Error message
empty block data
What it means
verifyBlockDataAndMetadata rejects any proposed block with nil Data or zero transactions. SmartBFT proposals must carry at least one request (except special cases handled elsewhere), so an empty block is treated as an invalid proposal.
Source
Thrown at orderer/consensus/smartbft/verifier.go:266
return errors.Errorf("previous header hash is %s but expected %s", thisHdrHashOfPrevHdr, prevHeaderHash)
}
dataHash, err := protoutil.BlockDataHash(block.Data)
if err != nil {
return err
}
dataHashString := hex.EncodeToString(block.Header.DataHash)
actualHashOfData := hex.EncodeToString(dataHash)
if dataHashString != actualHashOfData {
return errors.Errorf("data hash is %s but expected %s", dataHashString, actualHashOfData)
}
return nil
}
func (v *Verifier) verifyBlockDataAndMetadata(block *cb.Block, metadata []byte) ([]types.RequestInfo, error) {
if block.Data == nil || len(block.Data.Data) == 0 {
return nil, errors.New("empty block data")
}
if block.Metadata == nil || len(block.Metadata.Metadata) < len(cb.BlockMetadataIndex_name) {
return nil, errors.New("block metadata is either missing or contains too few entries")
}
signatureMetadata, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
if err != nil {
return nil, err
}
ordererMetadataFromSignature := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(signatureMetadata.Value, ordererMetadataFromSignature); err != nil {
return nil, errors.Wrap(err, "failed unmarshaling OrdererBlockMetadata")
}
// Ensure the view metadata in the block signature and in the proposal are the same
metadataInBlock := &smartbftprotos.ViewMetadata{}View on GitHub (pinned to 2736b63f8f)
Solutions
- Fix the batcher/leader to only propose blocks containing at least one request
- Check the request-batching timeouts and queue: ensure requests are collected before proposing
- Validate the proposal bytes before calling VerifyProposal; discard empty proposals
- If seen after an upgrade, check for regressions in block assembly code
Example fix
// before
if len(pendingRequests) == 0 { propose(block) }
// after
if len(pendingRequests) == 0 { return } // do not propose an empty block Defensive patterns
Strategy: validation
Validate before calling
if block.Data == nil || len(block.Data.Data) == 0 {
return errors.New("refusing to verify/propose an empty block")
} Type guard
func hasBlockData(b *cb.Block) bool { return b != nil && b.Data != nil && len(b.Data.Data) > 0 } Try / catch
if err := verifyProposal(...); err != nil && err.Error() == "empty block data" {
logger.Warn("leader proposed an empty block; skip and await valid proposal")
} Prevention
- Batcher should only assemble proposals when at least one request is pending
- Guard proposal construction against empty request queues
- Validate deserialized proposals before verification
- Check batching timeout configuration so batches are drained correctly
When it happens
Trigger: VerifyProposal receives a block where block.Data == nil or len(block.Data.Data) == 0 — e.g. a leader assembled a block with no batched requests and submitted it for verification.
Common situations: A leader bug assembling an empty batch; a proposal drained of its requests by faulty request batching logic; corrupted proposal deserialization losing the Data field; testing/misuse of VerifyProposal with a synthetic empty block.
Related errors
- block metadata is either missing or contains too few entries
- cannot create proposal, due to %s
- Cannot create proposal, due to %s
- no chaincode name is provided, channel id [%s]
- pending config does not match calculated expected config
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/7aa1d95bc60122e1.
Report an issue: GitHub.