{"record":{"id":"7aa1d95bc60122e1","repo":"hyperledger/fabric","slug":"empty-block-data-7aa1d9","errorCode":null,"errorMessage":"empty block data","messagePattern":"empty block data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/verifier.go","lineNumber":266,"sourceCode":"\t\treturn errors.Errorf(\"previous header hash is %s but expected %s\", thisHdrHashOfPrevHdr, prevHeaderHash)\n\t}\n\n\tdataHash, err := protoutil.BlockDataHash(block.Data)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdataHashString := hex.EncodeToString(block.Header.DataHash)\n\n\tactualHashOfData := hex.EncodeToString(dataHash)\n\tif dataHashString != actualHashOfData {\n\t\treturn errors.Errorf(\"data hash is %s but expected %s\", dataHashString, actualHashOfData)\n\t}\n\treturn nil\n}\n\nfunc (v *Verifier) verifyBlockDataAndMetadata(block *cb.Block, metadata []byte) ([]types.RequestInfo, error) {\n\tif block.Data == nil || len(block.Data.Data) == 0 {\n\t\treturn nil, errors.New(\"empty block data\")\n\t}\n\n\tif block.Metadata == nil || len(block.Metadata.Metadata) < len(cb.BlockMetadataIndex_name) {\n\t\treturn nil, errors.New(\"block metadata is either missing or contains too few entries\")\n\t}\n\n\tsignatureMetadata, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tordererMetadataFromSignature := &cb.OrdererBlockMetadata{}\n\tif err := proto.Unmarshal(signatureMetadata.Value, ordererMetadataFromSignature); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed unmarshaling OrdererBlockMetadata\")\n\t}\n\n\t// Ensure the view metadata in the block signature and in the proposal are the same\n\n\tmetadataInBlock := &smartbftprotos.ViewMetadata{}","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/verifier.go#L248-L284","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nif len(pendingRequests) == 0 { propose(block) }\n// after\nif len(pendingRequests) == 0 { return } // do not propose an empty block","handlingStrategy":"validation","validationCode":"if block.Data == nil || len(block.Data.Data) == 0 {\n    return errors.New(\"refusing to verify/propose an empty block\")\n}","typeGuard":"func hasBlockData(b *cb.Block) bool { return b != nil && b.Data != nil && len(b.Data.Data) > 0 }","tryCatchPattern":"if err := verifyProposal(...); err != nil && err.Error() == \"empty block data\" {\n    logger.Warn(\"leader proposed an empty block; skip and await valid proposal\")\n}","preventionTips":["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"],"tags":["smartbft","fabric","block-data","proposal"],"backgroundTag":"empty-block-data","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}