dgraph-io/badger · error
This API can only be called in managed mode.
Error message
This API can only be called in managed mode.
What it means
NewStreamAt panics when the DB is NOT in managed mode. NewStreamAt reads at an explicit timestamp, which is only meaningful when the user controls commit timestamps (managed transactions); in normal mode it would return wrong/empty data, so the library refuses it with a panic.
Source
Thrown at stream.go:499
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)
if err := proto.Unmarshal(s, kv); err != nil {
return err
}
list.Kv = append(list.Kv, kv)
return nil
})
return &list, err
}View on GitHub (pinned to 2a001d466f)
Solutions
- Open the DB in managed mode with badger.OpenManaged(opts) (or WithManagedTxns(true)) so NewStreamAt is valid
- If the DB is unmanaged, replace NewStreamAt with db.NewStream() which reads up to the latest visible timestamp
- Guard the call site on db.Opts().ManagedTxnsMode to pick the right stream constructor
Example fix
// before db, _ := badger.Open(opts) // unmanaged stream := db.NewStreamAt(ts) // panics // after db, _ := badger.OpenManaged(opts) stream := db.NewStreamAt(db.MaxVersion())
Defensive patterns
Strategy: try-catch
Validate before calling
func canUseNewStreamAt(db *badger.DB) bool { return isManagedDB(db) } // true only when opened via OpenManaged / WithManagedTxns(true) Type guard
func recoverPanicString(r interface{}) (string, bool) {
s, ok := r.(string)
return s, ok
} Try / catch
func safeNewStreamAt(db *badger.DB, readTs uint64) (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 not in managed mode: use NewStream()")
return
}
panic(r)
}
}()
s = db.NewStreamAt(readTs)
return
} Prevention
- Open with badger.OpenManaged when you need timestamp-based streaming (NewStreamAt, restore at ts)
- Centralize DB construction so managed/unmanaged mode is a single config decision
- Branch stream creation on mode: NewStream() for unmanaged, NewStreamAt(MaxVersion()) for managed
When it happens
Trigger: Calling db.NewStreamAt(readTs) on a DB opened with badger.Open (unmanaged), directly or via helpers like getSampleKeys/StreamDB that assume a managed DB.
Common situations: Mixing OpenManaged and Open across environments (test uses managed, prod does not); using managed-only restore/stream utilities against a normal DB instance.
Related errors
- This API can not 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/ac1d1a45852af107.
Report an issue: GitHub.