hyperledger/fabric · error
Nil value not allowed
Error message
Nil value not allowed
What it means
UpdateBatch.Put panics if the value is nil. LevelDB batches cannot carry nil values in this wrapper, and the ledger relies on non-nil (possibly empty) byte slices for tombstones/metadata. Passing nil instead of an empty slice is a programming error and is treated as a hard panic.
Source
Thrown at common/ledger/util/leveldbhelper/leveldb_provider.go:322
// Close closes the DBHandle after its db data have been deleted
func (h *DBHandle) Close() {
if h.closeFunc != nil {
h.closeFunc()
}
}
// UpdateBatch encloses the details of multiple `updates`
type UpdateBatch struct {
leveldbBatch *leveldb.Batch
dbName string
size int
}
// Put adds a KV
func (b *UpdateBatch) Put(key []byte, value []byte) {
if value == nil {
panic("Nil value not allowed")
}
k := constructLevelKey(b.dbName, key)
b.leveldbBatch.Put(k, value)
b.size += len(k) + len(value)
}
// Delete deletes a Key and associated value
func (b *UpdateBatch) Delete(key []byte) {
k := constructLevelKey(b.dbName, key)
b.size += len(k)
b.leveldbBatch.Delete(k)
}
// Size returns the current size of the batch
func (b *UpdateBatch) Size() int {
return b.size
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Replace nil with an empty slice: put(key, []byte{}) when a nil-value delete/tombstone is intended
- Fix upstream code so values are never nil on the success path — check errors before Put
- Add a caller-side nil check before invoking Put to fail gracefully instead of panicking
Example fix
// before
batch.Put(key, value) // panics when value == nil
// after
if value == nil {
value = []byte{}
}
batch.Put(key, value) Defensive patterns
Strategy: validation
Validate before calling
func safePut(b *leveldbhelper.UpdateBatch, key, value []byte) error {
if value == nil { return errors.New("value must not be nil; use []byte{} for empty") }
b.Put(key, value)
return nil
} Type guard
func isPuttable(value []byte) bool { return value != nil } Try / catch
func() {
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && s == "Nil value not allowed" {
log.Error("nil value passed to UpdateBatch.Put — use []byte{} instead")
}
}
}()
batch.Put(key, value)
}() Prevention
- Always use []byte{} instead of nil for empty values
- Check errors from value-producing helpers before passing results to Put
- Guard map lookups: if v, ok := m[k]; ok { batch.Put(k, v) }
- Wrap Put calls in a helper that asserts non-nil values
When it happens
Trigger: Calling UpdateBatch.Put(key, nil) — e.g. in add/deleteIndexEntriesRange/ImportFromSnapshot paths when a computed value is nil because an upstream lookup failed or a variable was left uninitialized instead of set to []byte{}.
Common situations: Passing the result of a map lookup (missing key returns nil) straight into Put; returning nil from a serialization helper on error and ignoring the error; refactoring that replaced []byte{} with nil.
Related errors
- Could not get block file info for current block file from db
- Could not save next block file info to db: %s
- error in block index: %s
- Error creating dir if missing: %s
- Error acquiring lock on file %s: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/1c6ba38ea9206821.
Report an issue: GitHub.