dgraph-io/badger · error
ErrEmptyKey
ErrEmptyKey
Error message
Key cannot be empty
What it means
ErrEmptyKey is returned when an update function is given a key of length zero (errors.go:40). Both Txn.modify (txn.go:360) and the IndexCache/Get path (db.go:1437) reject empty keys since Badger cannot store or look them up meaningfully.
Source
Thrown at errors.go:40
// ErrKeyNotFound is returned when key isn't found on a txn.Get.
ErrKeyNotFound = stderrors.New("Key not found")
// ErrTxnTooBig is returned if too many writes are fit into a single transaction.
ErrTxnTooBig = stderrors.New("Txn is too big to fit into one request")
// ErrConflict is returned when a transaction conflicts with another transaction. This can
// happen if the read rows had been updated concurrently by another transaction.
ErrConflict = stderrors.New("Transaction Conflict. Please retry")
// ErrReadOnlyTxn is returned if an update function is called on a read-only transaction.
ErrReadOnlyTxn = stderrors.New("No sets or deletes are allowed in a read-only transaction")
// ErrDiscardedTxn is returned if a previously discarded transaction is reused.
ErrDiscardedTxn = stderrors.New("This transaction has been discarded. Create a new one")
// ErrEmptyKey is returned if an empty key is passed on an update function.
ErrEmptyKey = stderrors.New("Key cannot be empty")
// ErrInvalidKey is returned if the key has a special !badger! prefix,
// reserved for internal usage.
ErrInvalidKey = stderrors.New("Key is using a reserved !badger! prefix")
// ErrBannedKey is returned if the read/write key belongs to any banned namespace.
ErrBannedKey = stderrors.New("Key is using the banned prefix")
// ErrThresholdZero is returned if threshold is set to zero, and value log GC is called.
// In such a case, GC can't be run.
ErrThresholdZero = stderrors.New(
"Value log GC can't run because threshold is set to zero")
// ErrNoRewrite is returned if a call for value log GC doesn't result in a log file rewrite.
ErrNoRewrite = stderrors.New(
"Value log GC attempt didn't result in any cleanup")
// ErrRejected is returned if a value log GC is called either while another GC is running, orView on GitHub (pinned to 2a001d466f)
Solutions
- Validate len(key) > 0 before calling Set/Delete/Get and skip or error on your side
- Fix key construction so every key has a non-empty prefix/field
- Guard against nil slices (a nil []byte has len 0)
Example fix
// before
txn.Set(key, value) // key may be empty -> ErrEmptyKey
// after
if len(key) == 0 {
return fmt.Errorf("skipping record with empty key")
}
txn.Set(key, value) Defensive patterns
Strategy: validation
Validate before calling
if len(key) == 0 {
return errors.New("refusing DB write with empty key")
} Type guard
func validKey(key []byte) bool { return len(key) > 0 && !bytes.HasPrefix(key, []byte("!badger!")) } Try / catch
if err := txn.Set(key, val); err != nil {
if errors.Is(err, badger.ErrEmptyKey) {
return fmt.Errorf("empty key for record %v: %w", rec, err)
}
return err
} Prevention
- Validate keys at the boundary where records are built
- Check for nil slices — nil []byte has length 0
- Unit-test key construction with edge-case records
When it happens
Trigger: txn.Set(nil, val) or txn.Set([]byte{}, val); txn.Delete with an empty key; GetIndexFor/lookup APIs (db.go:1437) receiving an empty key; a variable holding a key that was never populated.
Common situations: Dynamic key construction where a prefix/format produced "", unmarshalling records with missing fields into keys, nil byte slices from earlier failed operations.
Related errors
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/7bfdb46ab9f9bd9a.
Report an issue: GitHub.