hyperledger/fabric · critical

Header.DataHash is different from Hash(block.Data) for block

Error message

Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]

What it means

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.

Source

Thrown at internal/peer/gossip/mcs.go:160

	}

	if channelID != string(chainID) {
		return fmt.Errorf("Invalid block's channel id. Expected [%s]. Given [%s]", chainID, channelID)
	}

	// - Unmarshal medatada
	if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
		return fmt.Errorf("Block with id [%d] on channel [%s] does not have metadata. Block not valid.", block.Header.Number, chainID)
	}

	dataHash, err := protoutil.BlockDataHash(block.Data)
	if err != nil {
		return err
	}
	// - Verify that Header.DataHash is equal to the hash of block.Data
	// This is to ensure that the header is consistent with the data carried by this block
	if !bytes.Equal(dataHash, block.Header.DataHash) {
		return fmt.Errorf("Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]", block.Header.Number, chainID)
	}

	return s.verifyHeaderAndMetadata(channelID, block)
}

func (s *MSPMessageCryptoService) verifyHeaderAndMetadata(channelID string, block *pcommon.Block) error {
	// Get the policy manager for channelID
	cpm := s.channelPolicyManagerGetter.Manager(channelID)
	if cpm == nil {
		return fmt.Errorf("Could not acquire policy manager for channel %s", channelID)
	}
	mcsLogger.Debugf("Got policy manager for channel [%s]", channelID)

	// Get block validation policy
	policy, ok := cpm.GetPolicy(policies.BlockValidation)
	// ok is true if it was the policy requested, or false if it is the default policy
	mcsLogger.Debugf("Got block validation policy for channel [%s] with flag [%t]", channelID, ok)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Discard the block and re-fetch from the orderer or a trusted peer
  2. Check storage integrity (ledger/block files) if multiple blocks fail hash verification
  3. In code/tests, always build blocks with protoutil.CreateBlockHash/BlockDataHash so the header hash matches data

Example fix

// before
block.Header.DataHash = someOtherHash
// after
dataHash, _ := protoutil.BlockDataHash(block.Data)
block.Header.DataHash = dataHash
Defensive patterns

Strategy: validation

Validate before calling

func dataHashConsistent(b *pcommon.Block) bool {
    if b == nil || b.Header == nil || b.Data == nil {
        return false
    }
    h, err := protoutil.BlockDataHash(b.Data)
    if err != nil {
        return false
    }
    return bytes.Equal(h, b.Header.DataHash)
}

Type guard

func dataHashConsistent(b *pcommon.Block) bool {
    if b == nil || b.Header == nil || b.Data == nil {
        return false
    }
    h, err := protoutil.BlockDataHash(b.Data)
    if err != nil {
        return false
    }
    return bytes.Equal(h, b.Header.DataHash)
}

if !dataHashConsistent(block) {
    return errors.New("block data/header hash mismatch, discarding")
}

Try / catch

if err := cryptoService.VerifyBlock(chainID, seqNum, block); err != nil {
    if strings.Contains(err.Error(), "Header.DataHash is different") {
        log.Errorf("corrupt/tampered block %d on %s, refetching", seqNum, chainID)
        return refetchBlock(chainID, seqNum)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/fff966461a2d0fed. Report an issue: GitHub.