{"record":{"id":"6139c07791d60896","repo":"hyperledger/fabric","slug":"blocknum-should-be-greater-than-0","errorCode":null,"errorMessage":"blockNum should be greater than 0","messagePattern":"blockNum should be greater than 0","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/confighistory/db_helper.go","lineNumber":76,"sourceCode":"\nfunc (p *dbProvider) getDB(id string) *db {\n\treturn &db{p.GetDBHandle(id)}\n}\n\nfunc (b *batch) add(ns, key string, blockNum uint64, value []byte) {\n\tlogger.Debugf(\"add() - {%s, %s, %d}\", ns, key, blockNum)\n\tk, v := encodeCompositeKey(ns, key, blockNum), value\n\tb.Put(k, v)\n}\n\nfunc (d *db) writeBatch(batch *batch, sync bool) error {\n\treturn d.WriteBatch(batch.UpdateBatch, sync)\n}\n\nfunc (d *db) mostRecentEntryBelow(blockNum uint64, ns, key string) (*compositeKV, error) {\n\tlogger.Debugf(\"mostRecentEntryBelow() - {%s, %s, %d}\", ns, key, blockNum)\n\tif blockNum == 0 {\n\t\treturn nil, errors.New(\"blockNum should be greater than 0\")\n\t}\n\n\tstartKey := encodeCompositeKey(ns, key, blockNum-1)\n\tstopKey := append(encodeCompositeKey(ns, key, 0), byte(0))\n\n\titr, err := d.GetIterator(startKey, stopKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer itr.Release()\n\tif !itr.Next() {\n\t\tlogger.Debugf(\"Key no entry found. Returning nil\")\n\t\treturn nil, nil\n\t}\n\tk, v := decodeCompositeKey(itr.Key()), itr.Value()\n\treturn &compositeKV{k, v}, nil\n}\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/confighistory/db_helper.go#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\ninfo, _ := mgr.MostRecentCollectionConfigBelow(0, ns, coll)\n// after\nvar info *ledger.CollectionConfigInfo\nif blockNum > 0 {\n    info, _ = mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)\n}","handlingStrategy":"validation","validationCode":"func safeMostRecentConfig(mgr *mgr, blockNum uint64, ns, coll string) (*ledger.CollectionConfigInfo, error) {\n    if blockNum == 0 {\n        return nil, nil // no config can exist below block 0\n    }\n    return mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)\n}","typeGuard":"func blockNumValid(blockNum uint64) bool {\n    return blockNum > 0\n}","tryCatchPattern":"info, err := mgr.MostRecentCollectionConfigBelow(blockNum, ns, coll)\nif err != nil {\n    if err.Error() == \"blockNum should be greater than 0\" {\n        return nil, nil // treat as \"no config below block 0\"\n    }\n    return nil, err\n}","preventionTips":["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"],"tags":["fabric","ledger","config-history","argument-validation"],"backgroundTag":"invalid-block-number","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}