dgraph-io/badger · error
cannot use NewWriteBatch in managed mode. Use NewWriteBatchA
Error message
cannot use NewWriteBatch in managed mode. Use NewWriteBatchAt instead
What it means
NewWriteBatch creates a WriteBatch that picks its own commit timestamps. In managed mode timestamps must be supplied by the caller, so Badger forbids NewWriteBatch and requires NewWriteBatchAt(ts) which pins the write version. The panic fires at construction time before any writes are buffered.
Source
Thrown at batch.go:41
sync.Mutex
txn *Txn
db *DB
throttle *y.Throttle
err atomic.Value
isManaged bool
commitTs uint64
finished bool
}
// NewWriteBatch creates a new WriteBatch. This provides a way to conveniently do a lot of writes,
// batching them up as tightly as possible in a single transaction and using callbacks to avoid
// waiting for them to commit, thus achieving good performance. This API hides away the logic of
// creating and committing transactions. Due to the nature of SSI guaratees provided by Badger,
// blind writes can never encounter transaction conflicts (ErrConflict).
func (db *DB) NewWriteBatch() *WriteBatch {
if db.opt.managedTxns {
panic("cannot use NewWriteBatch in managed mode. Use NewWriteBatchAt instead")
}
return db.newWriteBatch(false)
}
func (db *DB) newWriteBatch(isManaged bool) *WriteBatch {
return &WriteBatch{
db: db,
isManaged: isManaged,
txn: db.newTransaction(true, isManaged),
throttle: y.NewThrottle(16),
}
}
// SetMaxPendingTxns sets a limit on maximum number of pending transactions while writing batches.
// This function should be called before using WriteBatch. Default value of MaxPendingTxns is
// 16 to minimise memory usage.
func (wb *WriteBatch) SetMaxPendingTxns(max int) {
wb.throttle = y.NewThrottle(max)View on GitHub (pinned to 2a001d466f)
Solutions
- Use db.NewWriteBatchAt(writeTs) instead, passing the managed write timestamp
- Call wb.SetEntryAt(e, ts) per entry if per-entry timestamps are needed
- Drop WithManagedTransactions(true) from DB options if managed mode is not actually required
Example fix
// before
wb := db.NewWriteBatch()
// after
wb := db.NewWriteBatchAt(writeTs)
err := wb.SetEntryAt(&badger.Entry{Key: key, Value: val}, writeTs) Defensive patterns
Strategy: validation
Validate before calling
var wb *badger.WriteBatch
if managed {
wb = db.NewWriteBatchAt(writeTs)
} else {
wb = db.NewWriteBatch()
} Prevention
- Encapsulate WriteBatch creation in one helper aware of managed mode
- Audit NewWriteBatch call sites when toggling WithManagedTransactions
- Prefer NewWriteBatchAt in any timestamp-controlled pipeline
When it happens
Trigger: Calling db.NewWriteBatch() on a DB opened with WithManagedTransactions(true).
Common situations: Applications that switched to managed mode for timestamp control (streaming writes, Dgraph) but kept legacy NewWriteBatch call sites.
Related errors
- Update can only be used with managedDB=false.
- cannot use NewWriteBatchAt with managedDB=false. Use NewWrit
- cannot use NewManagedWriteBatch with managedDB=false. Use Ne
- SetEntryAt can only be used in managed mode. Use SetEntry in
- Cannot use NewTransactionAt with managedDB=false. Use NewTra
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/73ba6012dec9a097.
Report an issue: GitHub.