hyperledger/fabric · error
blockNum should be greater than 0
Error message
blockNum should be greater than 0
What it means
confighistory db's mostRecentEntryBelow requires a block number above 0 because it searches for entries strictly below the given blockNum using blockNum-1 as the start key; blockNum==0 has no lower bound and would produce an invalid iterator range.
Source
Thrown at core/ledger/confighistory/db_helper.go:76
func (p *dbProvider) getDB(id string) *db {
return &db{p.GetDBHandle(id)}
}
func (b *batch) add(ns, key string, blockNum uint64, value []byte) {
logger.Debugf("add() - {%s, %s, %d}", ns, key, blockNum)
k, v := encodeCompositeKey(ns, key, blockNum), value
b.Put(k, v)
}
func (d *db) writeBatch(batch *batch, sync bool) error {
return d.WriteBatch(batch.UpdateBatch, sync)
}
func (d *db) mostRecentEntryBelow(blockNum uint64, ns, key string) (*compositeKV, error) {
logger.Debugf("mostRecentEntryBelow() - {%s, %s, %d}", ns, key, blockNum)
if blockNum == 0 {
return nil, errors.New("blockNum should be greater than 0")
}
startKey := encodeCompositeKey(ns, key, blockNum-1)
stopKey := append(encodeCompositeKey(ns, key, 0), byte(0))
itr, err := d.GetIterator(startKey, stopKey)
if err != nil {
return nil, err
}
defer itr.Release()
if !itr.Next() {
logger.Debugf("Key no entry found. Returning nil")
return nil, nil
}
k, v := decodeCompositeKey(itr.Key()), itr.Value()
return &compositeKV{k, v}, nil
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Guard the call site: only query when targetBlockNum > 0, otherwise return a nil config directly
- Initialize collection config lookups so block 0 requests short-circuit without hitting the db
- Fix off-by-one logic in callers computing blockNum from current height (height 0 means no configs yet)
Example fix
// before
info, _ := mgr.MostRecentCollectionConfigBelow(0, ns, coll)
// after
var info *ledger.CollectionConfigInfo
if blockNum > 0 {
info, _ = mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)
} Defensive patterns
Strategy: validation
Validate before calling
func safeMostRecentConfig(mgr *mgr, blockNum uint64, ns, coll string) (*ledger.CollectionConfigInfo, error) {
if blockNum == 0 {
return nil, nil // no config can exist below block 0
}
return mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)
} Type guard
func blockNumValid(blockNum uint64) bool {
return blockNum > 0
} Try / catch
info, err := mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)
if err != nil {
if err.Error() == "blockNum should be greater than 0" {
return nil, nil // treat as "no config below block 0"
}
return nil, err
} Prevention
- Guard all blockNum inputs derived from ledger height (height 0 = no configs)
- Short-circuit zero-height ledgers before db queries
- Add unit tests covering blockNum=0 at config lookup boundaries
- Use uint64 comparisons carefully to avoid wrapping in blockNum-1
When it happens
Trigger: MostRecentCollectionConfigBelow (or an anonymous range wrapper) is called with blockNum=0 — i.e. asking for the most recent collection config committed before block 0, which cannot exist.
Common situations: Ledger code computing the config applicable at a block without guarding against block 0; tests or snapshot tooling passing a zero-height block; a ledger queried before any block has been committed.
Related errors
- config history for ledger [%s] exists. Incremental import is
- cannot obtain configuration history retriever, for collectio
- unexpected end of blockfile
- error opening block file %s
- error seeking block file [%s] to startOffset [%d]
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/6139c07791d60896.
Report an issue: GitHub.