hyperledger/fabric · error
index %d out of bounds (total %d blocks)
Error message
index %d out of bounds (total %d blocks)
What it means
VerifyBlockHash was asked to verify the hash chain of a block whose index exceeds the number of blocks actually present in the supplied buffer. The caller passed an indexInBuffer that points past the end of blockBuff, so verification cannot proceed. It is a caller/programming or truncation error, not block corruption.
Source
Thrown at orderer/common/cluster/util.go:220
clientConfigCopy.SecOpts.ServerRootCAs = endpointCriteria.TLSRootCAs
return clientConfigCopy.Dial(endpointCriteria.Endpoint)
}
// BlockSequenceVerifier verifies that the given consecutive sequence
// of blocks is valid.
type BlockSequenceVerifier func(blocks []*common.Block, channel string) error
// Dialer creates a gRPC connection to a remote address
type Dialer interface {
Dial(endpointCriteria EndpointCriteria) (*grpc.ClientConn, error)
}
// VerifyBlockHash verifies the hash chain of the block with the given index
// among the blocks of the given block buffer.
func VerifyBlockHash(indexInBuffer int, blockBuff []*common.Block) error {
if len(blockBuff) <= indexInBuffer {
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)",View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the caller computes indexInBuffer as the block's position within the same buffer it passes (typically the last index: len(blockBuff)-1).
- Check upstream code (verifyBlockSequence / BlockPuller) for early returns that shrink blockBuff while continuing to verify at the original index.
- If the buffer is genuinely short, re-pull the missing blocks from the source orderer before verifying.
Example fix
// before
err := cluster.VerifyBlockHash(seq, buffer) // seq is chain-height index
// after
if len(buffer) == 0 || seq < buffer[0].Header.Number || int(seq-buffer[0].Header.Number) >= len(buffer) {
return errors.New("block not present in buffer")
}
err := cluster.VerifyBlockHash(int(seq-buffer[0].Header.Number), buffer) Defensive patterns
Strategy: validation
Validate before calling
func canVerify(indexInBuffer int, blockBuff []*common.Block) bool {
return indexInBuffer >= 0 && indexInBuffer < len(blockBuff)
}
if canVerify(idx, buff) {
err := cluster.VerifyBlockHash(idx, buff)
} Type guard
func blockAt(buff []*common.Block, i int) (*common.Block, bool) {
if i < 0 || i >= len(buff) || buff[i] == nil {
return nil, false
}
return buff[i], true
} Prevention
- Always derive indexInBuffer from the same buffer you pass (e.g. len(buff)-1 or seq - buff[0].Header.Number).
- Re-pull missing blocks instead of verifying against a truncated buffer.
- Add unit tests around partial-buffer scenarios like TestVerifyBlockHash.
When it happens
Trigger: Calling VerifyBlockHash(indexInBuffer, blockBuff) where len(blockBuff) <= indexInBuffer — e.g. verifying the last block in a sequence using a buffer that was truncated by an earlier failure or by pull of fewer blocks than expected.
Common situations: Block pulling/replication between Raft orderers where the delivered buffer is shorter than the sequence being verified; off-by-one in caller code computing the index of a block in a partial buffer.
Related errors
- missing block header
- missing block data
- computed hash of block (%d) (%s) doesn't match claimed hash
- last block header hash is missing
- failed to verify transactions are well formed for block with
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0fc2df3e786828ab.
Report an issue: GitHub.