{"record":{"id":"fff966461a2d0fed","repo":"hyperledger/fabric","slug":"header-datahash-is-different-from-hash-block-data-fff966","errorCode":null,"errorMessage":"Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]","messagePattern":"Header\\.DataHash is different from Hash\\(block\\.Data\\) for block with id \\[(.+?)\\] on channel \\[(.+?)\\]","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/peer/gossip/mcs.go","lineNumber":160,"sourceCode":"\t}\n\n\tif channelID != string(chainID) {\n\t\treturn fmt.Errorf(\"Invalid block's channel id. Expected [%s]. Given [%s]\", chainID, channelID)\n\t}\n\n\t// - Unmarshal medatada\n\tif block.Metadata == nil || len(block.Metadata.Metadata) == 0 {\n\t\treturn fmt.Errorf(\"Block with id [%d] on channel [%s] does not have metadata. Block not valid.\", block.Header.Number, chainID)\n\t}\n\n\tdataHash, err := protoutil.BlockDataHash(block.Data)\n\tif err != nil {\n\t\treturn err\n\t}\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 fmt.Errorf(\"Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]\", block.Header.Number, chainID)\n\t}\n\n\treturn s.verifyHeaderAndMetadata(channelID, block)\n}\n\nfunc (s *MSPMessageCryptoService) verifyHeaderAndMetadata(channelID string, block *pcommon.Block) error {\n\t// Get the policy manager for channelID\n\tcpm := s.channelPolicyManagerGetter.Manager(channelID)\n\tif cpm == nil {\n\t\treturn fmt.Errorf(\"Could not acquire policy manager for channel %s\", channelID)\n\t}\n\tmcsLogger.Debugf(\"Got policy manager for channel [%s]\", channelID)\n\n\t// Get block validation policy\n\tpolicy, ok := cpm.GetPolicy(policies.BlockValidation)\n\t// ok is true if it was the policy requested, or false if it is the default policy\n\tmcsLogger.Debugf(\"Got block validation policy for channel [%s] with flag [%t]\", channelID, ok)\n","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/gossip/mcs.go#L142-L178","documentation":"VerifyBlock recomputes the hash of block.Data and requires it to equal Header.DataHash, proving the header matches the block payload. A mismatch means the block data was tampered with, corrupted in transit, or the header belongs to different data — the block is rejected.","triggerScenarios":"VerifyBlock called on a block where bytes.Equal(BlockDataHash(block.Data), block.Header.DataHash) is false — data modified after header creation, wrong serialization, or mixing fields from two blocks.","commonSituations":"Storage corruption in the block store; a mutated in-memory block in custom code or tests; interop problems where block data was re-encoded without updating the header hash.","solutions":["Discard the block and re-fetch from the orderer or a trusted peer","Check storage integrity (ledger/block files) if multiple blocks fail hash verification","In code/tests, always build blocks with protoutil.CreateBlockHash/BlockDataHash so the header hash matches data"],"exampleFix":"// before\nblock.Header.DataHash = someOtherHash\n// after\ndataHash, _ := protoutil.BlockDataHash(block.Data)\nblock.Header.DataHash = dataHash","handlingStrategy":"validation","validationCode":"func dataHashConsistent(b *pcommon.Block) bool {\n    if b == nil || b.Header == nil || b.Data == nil {\n        return false\n    }\n    h, err := protoutil.BlockDataHash(b.Data)\n    if err != nil {\n        return false\n    }\n    return bytes.Equal(h, b.Header.DataHash)\n}","typeGuard":"func dataHashConsistent(b *pcommon.Block) bool {\n    if b == nil || b.Header == nil || b.Data == nil {\n        return false\n    }\n    h, err := protoutil.BlockDataHash(b.Data)\n    if err != nil {\n        return false\n    }\n    return bytes.Equal(h, b.Header.DataHash)\n}\n\nif !dataHashConsistent(block) {\n    return errors.New(\"block data/header hash mismatch, discarding\")\n}","tryCatchPattern":"if err := cryptoService.VerifyBlock(chainID, seqNum, block); err != nil {\n    if strings.Contains(err.Error(), \"Header.DataHash is different\") {\n        log.Errorf(\"corrupt/tampered block %d on %s, refetching\", seqNum, chainID)\n        return refetchBlock(chainID, seqNum)\n    }\n    return err\n}","preventionTips":["Never mutate block.Data after the header hash is set","Recompute BlockDataHash after any in-memory block construction","Investigate storage integrity if hash mismatches appear across many blocks; treat them as tamper signals"],"tags":["fabric","gossip","integrity","block-hash"],"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"}