dgraph-io/badger · error
This API can not be called in managed mode.
Error message
This API can not be called in managed mode.
What it means
NewStream panics when the DB was opened with managed transactions (managedTxns=true). In managed mode the stream API must be driven via explicit timestamps (NewStreamAt), so the unmanaged NewStream entry point is disallowed. The library enforces this invariant with a panic rather than an error return.
Source
Thrown at stream.go:491
// Wait for key streaming to be over.
err := <-kvErr
return err
}
func (db *DB) newStream() *Stream {
return &Stream{
db: db,
NumGo: db.opt.NumGoroutines,
LogPrefix: "Badger.Stream",
MaxSize: maxStreamSize,
}
}
// NewStream creates a new Stream.
func (db *DB) NewStream() *Stream {
if db.opt.managedTxns {
panic("This API can not be called in managed mode.")
}
return db.newStream()
}
// NewStreamAt creates a new Stream at a particular timestamp. Should only be used with managed DB.
func (db *DB) NewStreamAt(readTs uint64) *Stream {
if !db.opt.managedTxns {
panic("This API can only be called in managed mode.")
}
stream := db.newStream()
stream.readTs = readTs
return stream
}
func BufferToKVList(buf *z.Buffer) (*pb.KVList, error) {
var list pb.KVList
err := buf.SliceIterate(func(s []byte) error {
kv := new(pb.KV)View on GitHub (pinned to 2a001d466f)
Solutions
- Open the DB in normal (unmanaged) mode with badger.Open(opts) if you want db.NewStream()/Backup to work
- If you must stay in managed mode, use db.NewStreamAt(readTs) with an explicit read timestamp instead of NewStream()
- For Backup in managed mode, drive the stream yourself via NewStreamAt and db.WriteTo/BackupStream-equivalent flow with a chosen readTs
Example fix
// before
badgerDB, _ := badger.Open(badger.DefaultOptions(dir).WithManagedTxns(true))
_, err := badgerDB.Backup(w, 0) // panics: NewStream in managed mode
// after
badgerDB, _ := badger.OpenManaged(badger.DefaultOptions(dir))
ts := badgerDB.MaxVersion()
stream := badgerDB.NewStreamAt(ts)
stream.Send = func(buf *z.Buffer) error { return w.Write(buf.Bytes()) }
if err := stream.Orchestrate(context.Background()); err != nil { /* ... */ } Defensive patterns
Strategy: try-catch
Validate before calling
func canUseNewStream(db *badger.DB) bool {
// Managed DBs reject NewStream; recover from the panic boundary instead.
return !isManaged(db)
} Type guard
func isManaged(db *badger.DB) bool {
defer func() { recover() }()
// Probe via API that behaves differently in managed mode, e.g.:
// db.MaxVersion() exists only meaningfully in managed mode; prefer
// tracking how you opened the DB in application state.
return db == nil
} Try / catch
func safeNewStream(db *badger.DB) (s *badger.Stream, err error) {
defer func() {
if r := recover(); r != nil {
if msg, ok := r.(string); ok && strings.Contains(msg, "managed mode") {
err = errors.New("db in managed mode: use NewStreamAt(readTs)")
return
}
panic(r)
}
}()
s = db.NewStream()
return
} Prevention
- Track whether the DB was opened with OpenManaged/Open(...WithManagedTxns(true)) in application config
- Use NewStreamAt with db.MaxVersion() whenever the DB is managed
- Keep separate code paths for managed and unmanaged DBs instead of sharing NewStream-based code
When it happens
Trigger: Calling db.NewStream() on a DB opened with badger.Open followed by WithManagedTxns(true) (or via OpenManaged); typically reached indirectly through db.Backup() when the DB is in managed mode.
Common situations: Configuring managed mode for Subscribe/versioned workflows but reusing unmanaged-mode backup/iterate code; copy-pasting example code written for a normal DB into a managed DB app.
Related errors
- This API can only be called in managed mode.
- ReadTs should not be retrieved for managed DB
- Cannot use NewTransactionAt with managedDB=false. Use NewTra
- ErrReadOnlyTxn
- ErrDiscardedTxn
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/6a2ae210e2306db9.
Report an issue: GitHub.