hyperledger/fabric · error
data hash is %s but expected %s
Error message
data hash is %s but expected %s
What it means
verifyHashChainAndDataHash recomputes the block data hash via protoutil.BlockDataHash and compares it to block.Header.DataHash. If the header's declared data hash does not match the actual data, the block content was altered or built incorrectly.
Source
Thrown at orderer/consensus/smartbft/verifier.go:259
func (v *Verifier) VerificationSequence() uint64 {
return v.VerificationSequencer.Sequence()
}
func verifyHashChainAndDataHash(block *cb.Block, prevHeaderHash string) error {
thisHdrHashOfPrevHdr := hex.EncodeToString(block.Header.PreviousHash)
if prevHeaderHash != thisHdrHashOfPrevHdr {
return errors.Errorf("previous header hash is %s but expected %s", thisHdrHashOfPrevHdr, prevHeaderHash)
}
dataHash, err := protoutil.BlockDataHash(block.Data)
if err != nil {
return err
}
dataHashString := hex.EncodeToString(block.Header.DataHash)
actualHashOfData := hex.EncodeToString(dataHash)
if dataHashString != actualHashOfData {
return errors.Errorf("data hash is %s but expected %s", dataHashString, actualHashOfData)
}
return nil
}
func (v *Verifier) verifyBlockDataAndMetadata(block *cb.Block, metadata []byte) ([]types.RequestInfo, error) {
if block.Data == nil || len(block.Data.Data) == 0 {
return nil, errors.New("empty block data")
}
if block.Metadata == nil || len(block.Metadata.Metadata) < len(cb.BlockMetadataIndex_name) {
return nil, errors.New("block metadata is either missing or contains too few entries")
}
signatureMetadata, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
if err != nil {
return nil, err
}
ordererMetadataFromSignature := &cb.OrdererBlockMetadata{}View on GitHub (pinned to 2736b63f8f)
Solutions
- Rebuild the proposal ensuring DataHash = protoutil.BlockDataHash(block.Data) as the final step after data assembly
- Audit any code that mutates block.Data between hash computation and proposal
- Verify all nodes run the same protoutil version for BlockDataHash
- Discard and re-propose the block from the current leader
Example fix
// before: hash computed before adding a transaction hash := protoutil.BlockDataHash(data) data.Data = append(data.Data, extraTx) // data changed after hashing // after: compute hash last block.Data.Data = append(block.Data.Data, extraTx) 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 errors.New("block.DataHash does not match block.Data; reject proposal")
} Type guard
func dataHashMatches(b *cb.Block) bool {
h, err := protoutil.BlockDataHash(b.Data)
return err == nil && bytes.Equal(h, b.Header.DataHash)
} Try / catch
if err := verifyHashChainAndDataHash(block, prevHash); err != nil && strings.Contains(err.Error(), "data hash") {
logger.Warn("proposal data tampered or incorrectly assembled; discarding")
} Prevention
- Compute DataHash as the last step of block assembly, after all data is final
- Never mutate block.Data after hashing
- Use protoutil.BlockDataHash consistently, no custom hashing
- Audit any middleware that touches block data
When it happens
Trigger: A proposal whose block.Header.DataHash was computed over different data than block.Data contains — e.g. data mutated after hashing, or hash computed with a different algorithm/serialization.
Common situations: A buggy custom block assembler or middleware mutating block.Data after hashing; version mismatch in hashing utilities; corrupted proposal in-flight; adversarial/buggy leader proposing inconsistent blocks.
Related errors
- data mismatch
- Header.DataHash is different from Hash(block.Data) for block
- pending config does not match calculated expected config
- without a system channel, a follower should have been create
- failed parsing smartbft configuration
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/39f0e98f91247eb0.
Report an issue: GitHub.