hyperledger/fabric · critical

computed hash of block (%d) (%s) doesn't match claimed hash

Error message

computed hash of block (%d) (%s) doesn't match claimed hash (%s)

What it means

VerifyBlockHash computed SHA-256 over the block's Data via protoutil.BlockDataHash and it does not equal the DataHash stored in the block's header. This means the block payload was altered after the header was signed/committed, or the wrong bytes were deserialized into Data. This is genuine evidence of data corruption or a tampered/corrupted block.

Source

Thrown at orderer/common/cluster/util.go:238

		return errors.Errorf("index %d out of bounds (total %d blocks)", indexInBuffer, len(blockBuff))
	}
	block := blockBuff[indexInBuffer]
	if block.Header == nil {
		return errors.New("missing block header")
	}
	if block.Data == nil {
		return errors.New("missing block data")
	}
	seq := block.Header.Number
	dataHash, err := protoutil.BlockDataHash(block.Data)
	if err != nil {
		return err
	}
	// Verify data hash matches the hash in the header
	if !bytes.Equal(dataHash, block.Header.DataHash) {
		computedHash := hex.EncodeToString(dataHash)
		claimedHash := hex.EncodeToString(block.Header.DataHash)
		return errors.Errorf("computed hash of block (%d) (%s) doesn't match claimed hash (%s)",
			seq, computedHash, claimedHash)
	}
	// We have a previous block in the buffer, ensure current block's previous hash matches the previous one.
	if indexInBuffer > 0 {
		prevBlock := blockBuff[indexInBuffer-1]
		currSeq := block.Header.Number
		if prevBlock.Header == nil {
			return errors.New("previous block header is nil")
		}
		prevSeq := prevBlock.Header.Number
		if prevSeq+1 != currSeq {
			return errors.Errorf("sequences %d and %d were received consecutively", prevSeq, currSeq)
		}
		if !bytes.Equal(block.Header.PreviousHash, protoutil.BlockHeaderHash(prevBlock.Header)) {
			claimedPrevHash := hex.EncodeToString(block.Header.PreviousHash)
			actualPrevHash := hex.EncodeToString(protoutil.BlockHeaderHash(prevBlock.Header))
			return errors.Errorf("block [%d]'s hash (%s) mismatches block [%d]'s prev block hash (%s)",
				prevSeq, actualPrevHash, currSeq, claimedPrevHash)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Do not use the affected block; force re-pull from a different orderer (restart the onboarding/catch-up process).
  2. Run filesystem/storage integrity checks (fsck, SMART) on the orderer's ledger volume.
  3. Verify the source orderer is an approved consenter and TLS certificates are correct to rule out a spoofed source.
  4. If a persisted block fails verification, restore the ledger from a snapshot or rejoin the node to the channel.

Example fix

// before
// trusting any block received over the wire
blockBuff = append(blockBuff, receivedBlock)
// after
if err := cluster.VerifyBlockHash(0, []*common.Block{receivedBlock}); err != nil {
    logger.Errorf("discarding corrupt block: %s", err)
    return err // re-pull from another orderer
}
blockBuff = append(blockBuff, receivedBlock)
Defensive patterns

Strategy: fallback

Validate before calling

computed, err := protoutil.BlockDataHash(b.Data)
if err != nil || !bytes.Equal(computed, b.Header.DataHash) {
    return errors.New("block data hash mismatch, re-pull required")
}

Try / catch

if err := cluster.VerifyBlockHash(idx, buff); err != nil {
    if strings.Contains(err.Error(), "doesn't match claimed hash") {
        // corrupt block: discard and re-pull from a different orderer
        logger.Errorf("corrupt block detected: %s", err)
        restartCatchupFromDifferentSource()
        return
    }
    return err
}

Prevention

When it happens

Trigger: A block pulled during replication (BlockPuller/verifyBlockSequence) whose Data bytes hash to something other than Header.DataHash — e.g. storage corruption, partial writes, or a malicious/misbehaving source.

Common situations: Disk corruption on an orderer's ledger; flaky storage/network flipping bytes during block transfer; pulling blocks from a rogue orderer that is not part of the consenter set.

Related errors


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