{"record":{"id":"87148d84cdd565f2","repo":"hyperledger/fabric","slug":"header-datahash-is-different-from-hash-block-data","errorCode":null,"errorMessage":"Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]; Header: %s, Data: %s","messagePattern":"Header\\.DataHash is different from Hash\\(block\\.Data\\) for block with id \\[(.+?)\\] on channel \\[(.+?)\\]; Header: (.+?), Data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"common/deliverclient/block_verification.go","lineNumber":260,"sourceCode":"// VerifyBlock checks block integrity and its relation to the chain, and verifies the signatures.\nfunc (a *BlockVerificationAssistant) VerifyBlock(block *common.Block) error {\n\tif err := a.verifyHeader(block); err != nil {\n\t\treturn err\n\t}\n\n\tif err := a.verifyMetadata(block); err != nil {\n\t\treturn err\n\t}\n\n\tdataHash, err := protoutil.BlockDataHash(block.Data)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to verify transactions are well formed for block with id [%d] on channel [%s]\", block.Header.Number, a.channelID)\n\t}\n\n\t// Verify that Header.DataHash is equal to the hash of block.Data\n\t// This is to ensure that the header is consistent with the data carried by this block\n\tif !bytes.Equal(dataHash, block.Header.DataHash) {\n\t\treturn errors.Errorf(\"Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]; Header: %s, Data: %s\",\n\t\t\tblock.Header.Number, a.channelID, hex.EncodeToString(block.Header.DataHash), hex.EncodeToString(dataHash))\n\t}\n\n\terr = a.sigVerifierFunc(block.Header, block.Metadata)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ta.lastBlockHeader = block.Header\n\ta.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)\n\n\treturn nil\n}\n\n// VerifyBlockAttestation does the same as VerifyBlock, except it assumes block.Data = nil. It therefore does not\n// compute the block.Data.Hash() and compare it to the block.Header.DataHash. This is used when the orderer\n// delivers a block with header & metadata only, as an attestation of block existence.\nfunc (a *BlockVerificationAssistant) VerifyBlockAttestation(block *common.Block) error {","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/deliverclient/block_verification.go#L242-L278","documentation":"VerifyBlock checks that block.Header.DataHash equals the computed hash of block.Data. A mismatch means the block header does not describe the data it carries — the block is tampered, corrupted, or fabricated — so the deliver client rejects it with this detailed message (header hash vs computed hash, hex-encoded).","triggerScenarios":"A block delivered by an untrusted/broken orderer whose header was computed over different data; data bytes altered in transit or storage; a hand-built block whose Header.DataHash wasn't computed with protoutil.BlockDataHash.","commonSituations":"Chain verification across restarts picking a wrong last-block anchor; corrupted ledger storage; hand-crafted blocks in test tooling; man-in-the-middle / misbehaving orderer scenarios.","solutions":["Re-fetch the block from a trusted orderer; if the mismatch persists across sources, investigate the orderer/consensus.","Re-anchor the verification assistant with the correct last block header hash (clone/lastBlockHeader state) if the mismatch starts at one block.","Check ledger file integrity (fsck, checksums, backup restore) for persisted blocks.","Never hand-set Header.DataHash; compute it with protoutil.BlockDataHash(block.Data)."],"exampleFix":"// before (hand-built block)\nblock := &common.Block{Header: &common.BlockHeader{Number: n}} // DataHash unset/wrong\n\n// after\nblock.Header.DataHash = protoutil.BlockDataHash(block.Data)","handlingStrategy":"validation","validationCode":"dataHash, err := protoutil.BlockDataHash(block.Data)\nif err != nil { return err }\nif !bytes.Equal(dataHash, block.Header.DataHash) {\n    return fmt.Errorf(\"block %d data hash mismatch; do not process this block\", block.Header.Number)\n}","typeGuard":"func dataHashConsistent(block *common.Block) bool {\n    if block == nil || block.Header == nil || block.Data == nil { return false }\n    h, err := protoutil.BlockDataHash(block.Data)\n    return err == nil && bytes.Equal(h, block.Header.DataHash)\n}","tryCatchPattern":"if err := bva.VerifyBlock(block, opts); err != nil {\n    if strings.Contains(err.Error(), \"different from Hash(block.Data)\") {\n        // treat block as tampered/corrupt: refetch from trusted orderer, alert\n    }\n    return err\n}","preventionTips":["Compute Header.DataHash with protoutil.BlockDataHash, never by hand","Treat hash mismatches as integrity incidents: refetch, verify chain, alert","Keep signed backups/checksums of persisted block files","Only trust blocks delivered over authenticated TLS streams from configured orderers"],"tags":["hyperledger-fabric","block-verification","tamper-detection","integrity"],"backgroundTag":"block-hash-mismatch","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"}