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

  1. Open the DB in normal (unmanaged) mode with badger.Open(opts) if you want db.NewStream()/Backup to work
  2. If you must stay in managed mode, use db.NewStreamAt(readTs) with an explicit read timestamp instead of NewStream()
  3. 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

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


AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05). Data as JSON: /api/errors/6a2ae210e2306db9. Report an issue: GitHub.