{"record":{"id":"cd3cc2c98c23cde0","repo":"hyperledger/fabric","slug":"invalid-block-header-must-be-different-from-nil","errorCode":null,"errorMessage":"invalid block, header must be different from nil, channel=%s","messagePattern":"invalid block, header must be different from nil, channel=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/deliverclient/block_verification.go","lineNumber":316,"sourceCode":"func (a *BlockVerificationAssistant) UpdateBlockHeader(block *common.Block) {\n\ta.lastBlockHeader = block.Header\n\ta.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)\n}\n\nfunc (a *BlockVerificationAssistant) verifyMetadata(block *common.Block) error {\n\tif block.Metadata == nil || len(block.Metadata.Metadata) < len(common.BlockMetadataIndex_name) {\n\t\treturn errors.Errorf(\"block with id [%d] on channel [%s] does not have metadata or contains too few entries\", block.Header.Number, a.channelID)\n\t}\n\n\treturn nil\n}\n\nfunc (a *BlockVerificationAssistant) verifyHeader(block *common.Block) error {\n\tif block == nil {\n\t\treturn errors.Errorf(\"block must be different from nil, channel=%s\", a.channelID)\n\t}\n\tif block.Header == nil {\n\t\treturn errors.Errorf(\"invalid block, header must be different from nil, channel=%s\", a.channelID)\n\t}\n\n\texpectedBlockNum := a.lastBlockHeader.Number + 1\n\tif expectedBlockNum != block.Header.Number {\n\t\treturn errors.Errorf(\"expected block number is [%d] but actual block number inside block is [%d]\", expectedBlockNum, block.Header.Number)\n\t}\n\n\tif len(a.lastBlockHeaderHash) != 0 {\n\t\tif !bytes.Equal(block.Header.PreviousHash, a.lastBlockHeaderHash) {\n\t\t\treturn errors.Errorf(\"Header.PreviousHash of block [%d] is different from Hash(block.Header) of previous block, on channel [%s], received: %s, expected: %s\",\n\t\t\t\tblock.Header.Number, a.channelID, hex.EncodeToString(block.Header.PreviousHash), hex.EncodeToString(a.lastBlockHeaderHash))\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":298,"sourceCodeEnd":332,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/deliverclient/block_verification.go#L298-L332","documentation":"BlockVerificationAssistant.verifyHeader rejects a delivered block whose Header field is nil. The deliver client verifies each block from the ordering service before handing it up, and a block without a header cannot be numbered, hash-chained, or validated, so it is refused immediately with the channel name included.","triggerScenarios":"VerifyBlock or VerifyBlockAttestation is called with a *common.Block that has Header == nil — i.e. a nil-adjacent/empty or malformed block envelope arrived from the deliver stream (or a caller constructed a block programmatically without populating Header).","commonSituations":"Corrupt or truncated gRPC deliver payloads; a misbehaving or buggy ordering node emitting empty blocks; unit/integration tests passing partially initialized common.Block structs; custom marshaling/deserialization bugs in code that builds blocks from protobuf payloads.","solutions":["Inspect the block received from the deliver stream and check why Header is unpopulated before it reaches VerifyBlock.","Verify the ordering service node is healthy and emitting well-formed blocks (compare against peers' blocks).","If the caller constructs the block, populate block.Header (Number, PreviousHash, DataHash) before calling VerifyBlock.","Add a nil/field check on block.Header at the call site to fail fast with a clearer local error."],"exampleFix":"// before\nblk := &common.Block{Data: data}\nassistant.VerifyBlock(blk)\n// after\nif blk.Header == nil {\n    return fmt.Errorf(\"refusing to verify block with nil header\")\n}\nblk.Header = &common.BlockHeader{Number: n, PreviousHash: prev, DataHash: hash}\nassistant.VerifyBlock(blk)","handlingStrategy":"validation","validationCode":"if blk == nil || blk.Header == nil {\n    return fmt.Errorf(\"block or block.Header is nil; not calling VerifyBlock\")\n}","typeGuard":"func hasHeader(b *common.Block) bool { return b != nil && b.Header != nil }","tryCatchPattern":"err := assistant.VerifyBlock(blk)\nif err != nil && strings.Contains(err.Error(), \"header must be different from nil\") {\n    // malformed block from stream: log, drop block, and re-sync from a trusted height\n}","preventionTips":["Always validate protobuf-decoded blocks for non-nil Header before verification.","Monitor ordering node health to catch nodes emitting malformed blocks.","In tests, use realistic block builders (protoutil) rather than hand-built structs."],"tags":["fabric","deliver-client","block-verification","malformed-block"],"backgroundTag":"malformed-block-missing-header","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}