hyperledger/fabric · critical

unexpected Previous block hash. Expected PreviousHash = [%x]

Error message

unexpected Previous block hash. Expected PreviousHash = [%x], PreviousHash referred in the latest block= [%x]

What it means

addBlock verifies that block.Header.PreviousHash equals the hash of the current chain tip (bcInfo.CurrentBlockHash). This cheap bytes comparison catches blocks that do not chain onto the ledger's last block, which usually indicates a fork, a block from a different chain, or an ordering-service bug. The block is rejected with this error.

Source

Thrown at common/ledger/blkstorage/blockfile_mgr.go:298

	mgr.currentFileWriter = nextFileWriter
	mgr.updateBlockfilesInfo(blkfilesInfo)
}

func (mgr *blockfileMgr) addBlock(block *common.Block) error {
	bcInfo := mgr.getBlockchainInfo()
	if block.Header.Number != bcInfo.Height {
		return errors.Errorf(
			"block number should have been %d but was %d",
			mgr.getBlockchainInfo().Height, block.Header.Number,
		)
	}

	// Add the previous hash check - Though, not essential but may not be a bad idea to
	// verify the field `block.Header.PreviousHash` present in the block.
	// This check is a simple bytes comparison and hence does not cause any observable performance penalty
	// and may help in detecting a rare scenario if there is any bug in the ordering service.
	if !bytes.Equal(block.Header.PreviousHash, bcInfo.CurrentBlockHash) {
		return errors.Errorf(
			"unexpected Previous block hash. Expected PreviousHash = [%x], PreviousHash referred in the latest block= [%x]",
			bcInfo.CurrentBlockHash, block.Header.PreviousHash,
		)
	}
	blockBytes, info := serializeBlock(block)
	blockHash := protoutil.BlockHeaderHash(block.Header)
	// Get the location / offset where each transaction starts in the block and where the block ends
	txOffsets := info.txOffsets
	currentOffset := mgr.blockfilesInfo.latestFileSize

	blockBytesLen := len(blockBytes)
	blockBytesEncodedLen := protowire.AppendVarint(nil, uint64(blockBytesLen))
	totalBytesToAppend := blockBytesLen + len(blockBytesEncodedLen)

	// Determine if we need to start a new file since the size of this block
	// exceeds the amount of space left in the current file
	if currentOffset+totalBytesToAppend > mgr.conf.maxBlockfileSize {
		mgr.moveToNextFile()

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the block source: reconnect to the correct ordering service / consensus cluster and re-fetch blocks from the ledger height
  2. Restore the ledger data from a consistent backup matching the same chain (same genesis block and orderer history)
  3. If the chain diverged, perform a ledger reset and re-sync from the canonical chain
  4. Check that genesis blocks/config match across environments before importing or syncing

Example fix

// before: trusting a stale/mismatched block feed
blk := fetchFromOrderer(number)
store.AddBlock(blk) // fails: PreviousHash != tip
// after: re-sync from ledger height against the canonical orderer
bcInfo, _ := store.GetBlockchainInfo()
blk := fetchFromCanonicalOrderer(bcInfo.Height)
store.AddBlock(blk)
Defensive patterns

Strategy: validation

Validate before calling

bcInfo, err := store.GetBlockchainInfo()
if err != nil { return err }
if !bytes.Equal(block.Header.PreviousHash, bcInfo.CurrentBlockHash) {
    return fmt.Errorf("refusing block %d: does not chain onto tip", block.Header.Number)
}

Try / catch

if err := store.AddBlock(block); err != nil {
    if strings.Contains(err.Error(), "unexpected Previous block hash") {
        // halt the feed, flag a possible fork/divergence, re-sync from canonical orderer
    }
    return err
}

Prevention

When it happens

Trigger: Adding a block whose PreviousHash differs from the stored hash of the last committed block — e.g., after restoring block files inconsistently, importing blocks from a diverged branch, or two orderers producing conflicting chains.

Common situations: Ledger restored from mixed/partial backups; peer connected to a diverged ordering service (Raft reconfiguration/fork); snapshot import combined with blocks from a different network; test harnesses reusing blocks across ledgers.

Related errors


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