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]; Header: %s, Data: %s

What it means

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).

Source

Thrown at common/deliverclient/block_verification.go:260

// VerifyBlock checks block integrity and its relation to the chain, and verifies the signatures.
func (a *BlockVerificationAssistant) VerifyBlock(block *common.Block) error {
	if err := a.verifyHeader(block); err != nil {
		return err
	}

	if err := a.verifyMetadata(block); err != nil {
		return err
	}

	dataHash, err := protoutil.BlockDataHash(block.Data)
	if err != nil {
		return errors.Wrapf(err, "failed to verify transactions are well formed for block with id [%d] on channel [%s]", block.Header.Number, a.channelID)
	}

	// 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 errors.Errorf("Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]; Header: %s, Data: %s",
			block.Header.Number, a.channelID, hex.EncodeToString(block.Header.DataHash), hex.EncodeToString(dataHash))
	}

	err = a.sigVerifierFunc(block.Header, block.Metadata)
	if err != nil {
		return err
	}

	a.lastBlockHeader = block.Header
	a.lastBlockHeaderHash = protoutil.BlockHeaderHash(block.Header)

	return nil
}

// VerifyBlockAttestation does the same as VerifyBlock, except it assumes block.Data = nil. It therefore does not
// compute the block.Data.Hash() and compare it to the block.Header.DataHash. This is used when the orderer
// delivers a block with header & metadata only, as an attestation of block existence.
func (a *BlockVerificationAssistant) VerifyBlockAttestation(block *common.Block) error {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Re-fetch the block from a trusted orderer; if the mismatch persists across sources, investigate the orderer/consensus.
  2. Re-anchor the verification assistant with the correct last block header hash (clone/lastBlockHeader state) if the mismatch starts at one block.
  3. Check ledger file integrity (fsck, checksums, backup restore) for persisted blocks.
  4. Never hand-set Header.DataHash; compute it with protoutil.BlockDataHash(block.Data).

Example fix

// before (hand-built block)
block := &common.Block{Header: &common.BlockHeader{Number: n}} // DataHash unset/wrong

// after
block.Header.DataHash = protoutil.BlockDataHash(block.Data)
Defensive patterns

Strategy: validation

Validate before calling

dataHash, err := protoutil.BlockDataHash(block.Data)
if err != nil { return err }
if !bytes.Equal(dataHash, block.Header.DataHash) {
    return fmt.Errorf("block %d data hash mismatch; do not process this block", block.Header.Number)
}

Type guard

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

Try / catch

if err := bva.VerifyBlock(block, opts); err != nil {
    if strings.Contains(err.Error(), "different from Hash(block.Data)") {
        // treat block as tampered/corrupt: refetch from trusted orderer, alert
    }
    return err
}

Prevention

When it happens

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

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

Related errors


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