hyperledger/fabric · critical
Header.PreviousHash of block [%d] is different from Hash(blo
Error message
Header.PreviousHash of block [%d] is different from Hash(block.Header) of previous block, on channel [%s], received: %s, expected: %s
What it means
After the block number check, verifyHeader validates the hash chain: block.Header.PreviousHash must equal the hash of the previous block's header (stored in a.lastBlockHeaderHash). A mismatch means the delivered block is not chained onto the block the client last accepted — evidence of a corrupted stream, a fork, or data tampering.
Source
Thrown at common/deliverclient/block_verification.go:326
return nil
}
func (a *BlockVerificationAssistant) verifyHeader(block *common.Block) error {
if block == nil {
return errors.Errorf("block must be different from nil, channel=%s", a.channelID)
}
if block.Header == nil {
return errors.Errorf("invalid block, header must be different from nil, channel=%s", a.channelID)
}
expectedBlockNum := a.lastBlockHeader.Number + 1
if expectedBlockNum != block.Header.Number {
return errors.Errorf("expected block number is [%d] but actual block number inside block is [%d]", expectedBlockNum, block.Header.Number)
}
if len(a.lastBlockHeaderHash) != 0 {
if !bytes.Equal(block.Header.PreviousHash, a.lastBlockHeaderHash) {
return errors.Errorf("Header.PreviousHash of block [%d] is different from Hash(block.Header) of previous block, on channel [%s], received: %s, expected: %s",
block.Header.Number, a.channelID, hex.EncodeToString(block.Header.PreviousHash), hex.EncodeToString(a.lastBlockHeaderHash))
}
}
return nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify the ordering node you are connected to is on the same chain as your peers (compare block hashes at a common height).
- Reconnect to a different/orderer-consensus-quorum-backed endpoint rather than a possibly forked node.
- If the client state is wrong, recompute lastBlockHeaderHash from a trusted local ledger block before resuming the stream.
- If a genuine fork/tampering is suspected, halt the client and follow the chain-repair procedures for the network.
Example fix
// before
// blindly resuming stream from a possibly forked orderer
deliverClient.Connect(seekInfoEnv, suspectEndpoint)
// after
if !bytes.Equal(headersAtHeight(orderer, h).Hash(), localLedgerBlockHash(h)) {
endpoint = selectOrdererOnSameChain(ordererEndpoints, localLedgerBlockHash)
}
deliverClient.Connect(seekInfoEnv, endpoint) Defensive patterns
Strategy: fallback
Validate before calling
if len(lastBlockHeaderHash) > 0 && !bytes.Equal(blk.Header.PreviousHash, lastBlockHeaderHash) {
return fmt.Errorf("hash chain broken at block %d; switching orderer", blk.Header.Number)
} Try / catch
if err := assistant.VerifyBlock(blk); err != nil {
if strings.Contains(err.Error(), "PreviousHash of block") {
// treat as possible fork: disconnect, try another orderer, compare chain hashes at a common height
}
} Prevention
- Seed lastBlockHeaderHash from a trusted source (your own ledger, not the remote orderer).
- Prefer connecting via multiple orderers and cross-check hashes at a common height.
- Never ignore hash-chain mismatches; they indicate forks or tampering.
- Keep genesis/config block verification enabled so clients detect divergent networks early.
When it happens
Trigger: VerifyBlock/VerifyBlockAttestation receives a block whose PreviousHash differs from the stored lastBlockHeaderHash (only when lastBlockHeaderHash is non-empty). Occurs when the orderer serves a divergent chain, a different channel's block leaks into the stream, or the client's lastBlockHeaderHash was seeded from the wrong block.
Common situations: Ordering service nodes with divergent chains after a configuration/consensus fault; connecting to an orderer that was forcibly refetched/different genesis; switching endpoints mid-stream to a node on a different branch; test setups seeding lastBlockHeaderHash incorrectly.
Related errors
- invalid block, header must be different from nil, channel=%s
- expected block number is [%d] but actual block number inside
- last block header hash is missing
- no endpoints
- could not create a signed Deliver SeekInfo message, somethin
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/24c703822a50693b.
Report an issue: GitHub.