dgraph-io/badger · error
block out of index
Error message
block out of index
What it means
Table.block returns this error when the requested block index is >= the number of block offsets in the table index (negative is asserted separately). It means the caller asked for a block that does not exist in this table.
Source
Thrown at table/table.go:555
}
index, err := t.readTableIndex()
y.Check(err)
t.opt.IndexCache.Set(t.indexKey(), index, int64(t.indexLen))
return index
}
func (t *Table) offsets(ko *fb.BlockOffset, i int) bool {
return t.fetchIndex().Offsets(ko, i)
}
// block function return a new block. Each block holds a ref and the byte
// slice stored in the block will be reused when the ref becomes zero. The
// caller should release the block by calling block.decrRef() on it.
func (t *Table) block(idx int, useCache bool) (*Block, error) {
y.AssertTruef(idx >= 0, "idx=%d", idx)
if idx >= t.offsetsLength() {
return nil, errors.New("block out of index")
}
if t.opt.BlockCache != nil {
key := t.blockCacheKey(idx)
blk, ok := t.opt.BlockCache.Get(key)
if ok && blk != nil {
// Use the block only if the increment was successful. The block
// could get evicted from the cache between the Get() call and the
// incrRef() call.
if blk.incrRef() {
return blk, nil
}
}
}
var ko fb.BlockOffset
y.AssertTrue(t.offsets(&ko, idx))
blk := &Block{offset: int(ko.Offset())}
blk.ref.Store(1)View on GitHub (pinned to 2a001d466f)
Solutions
- Guard the block index against offsetsLength() before calling t.block(idx, ...)
- Upgrade Badger — races between iteration and table dropping were fixed over time
- If it appears during open, treat the table as corrupt and restore it from backup
- Check that no custom code calls block() with hand-computed indices
Example fix
// before
blk, err := t.block(idx, true)
// after
if idx >= t.offsetsLength() {
return io.EOF // or handle gracefully
}
blk, err := t.block(idx, true) Defensive patterns
Strategy: type-guard
Type guard
func (t *table) hasBlock(idx int) bool {
return idx >= 0 && idx < t.offsetsLength()
}
// call site: if !hasBlock(idx) { return io.EOF } Try / catch
blk, err := tbl.block(idx, true)
if errors.Is(err, errBlockOutOfIndex) || err != nil && err.Error() == "block out of index" {
return io.EOF // end iteration gracefully
} Prevention
- Always bounds-check block indices against offsetsLength()
- Upgrade Badger to pick up iterator/cleanup race fixes
- Avoid custom code that indexes table blocks directly
When it happens
Trigger: Iterator code (seekToFirst, seekToLast, seekHelper, next, prev) or VerifyChecksum computing a block index from offsets and running past the last block — usually due to a stale/corrupt index, concurrent table deletion, or an out-of-range idx from binary search over corrupted offsets.
Common situations: Corrupted index lengths from damaged SSTs; race between iterators and table cleanup (DropAll/compaction) in older versions; custom code indexing t.offsets() directly.
Related errors
- invalid index length in footer. Data corrupted
- ErrValueLogSize
- ErrThresholdZero
- %s with size %d exceeded %d limit. %s: %s
- Unclosed iterator at time of Txn.Discard.
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/e293c2b5c6bf131b.
Report an issue: GitHub.