dgraph-io/badger · critical
txn callback is nil
Error message
txn callback is nil
What it means
runTxnCallback is Badger's internal dispatcher for commit callbacks used by CommitWith. It panics if the *txnCb struct itself is nil, which indicates an internal wiring bug in the commit path rather than user error. This panic runs inside a goroutine spawned by CommitWith, so it crashes the process if reached.
Source
Thrown at txn.go:683
return err
}
// If batchSet failed, LSM would not have been updated. So, no need to rollback anything.
// TODO: What if some of the txns successfully make it to value log, but others fail.
// Nothing gets updated to LSM, until a restart happens.
return txnCb()
}
type txnCb struct {
commit func() error
user func(error)
err error
}
func runTxnCallback(cb *txnCb) {
switch {
case cb == nil:
panic("txn callback is nil")
case cb.user == nil:
panic("Must have caught a nil callback for txn.CommitWith")
case cb.err != nil:
cb.user(cb.err)
case cb.commit != nil:
err := cb.commit()
cb.user(err)
default:
cb.user(nil)
}
}
// CommitWith acts like Commit, but takes a callback, which gets run via a
// goroutine to avoid blocking this function. The callback is guaranteed to run,
// so it is safe to increment sync.WaitGroup before calling CommitWith, and
// decrementing it in the callback; to block until all callbacks are run.
func (txn *Txn) CommitWith(cb func(error)) {
if cb == nil {View on GitHub (pinned to 2a001d466f)
Solutions
- Check the Badger version for known bugs in the CommitWith empty-transaction path and upgrade
- Ensure you never call CommitWith with a nil callback (that produces error 52 before this one)
- If using a fork, verify runTxnCallback is only invoked with a non-nil *txnCb allocated by CommitWith
Example fix
// before (fork/internal)
runTxnCallback(nil)
// after
if cb != nil { runTxnCallback(cb) } Defensive patterns
Strategy: validation
Validate before calling
if cb == nil { cb = func(error){} } // before any commit path involving CommitWith Try / catch
defer func(){ if r := recover(); r != nil { log.Fatalf("badger txn callback panic: %v", r) } }() // around goroutines is not possible; guard at CommitWith call site Prevention
- Never pass nil to CommitWith
- Keep CommitWith usage to the public API only; do not call runTxnCallback in forks
When it happens
Trigger: A nil *txnCb reaches runTxnCallback; this only happens via internal misuse of the callback plumbing (e.g. committing an empty txn whose callback path constructs no txnCb, or a library bug/patched code path passing nil).
Common situations: Using CommitWith on a transaction with no pending writes combined with managed/Read-only txn setups in older versions; custom forks that call runTxnCallback directly.
Related errors
- Must have caught a nil callback for txn.CommitWith
- Base level can't be zero.
- BlockCacheSize should be set since compression/encryption ar
- Cannot use GetSequence with managedDB=true.
- Cannot use GetSequence in read-only mode.
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/be1a2a6ca07f36d6.
Report an issue: GitHub.