{"record":{"id":"ac1d1a45852af107","repo":"dgraph-io/badger","slug":"this-api-can-only-be-called-in-managed-mode","errorCode":null,"errorMessage":"This API can only be called in managed mode.","messagePattern":"This API can only be called in managed mode\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"stream.go","lineNumber":499,"sourceCode":"\t\tdb:        db,\n\t\tNumGo:     db.opt.NumGoroutines,\n\t\tLogPrefix: \"Badger.Stream\",\n\t\tMaxSize:   maxStreamSize,\n\t}\n}\n\n// NewStream creates a new Stream.\nfunc (db *DB) NewStream() *Stream {\n\tif db.opt.managedTxns {\n\t\tpanic(\"This API can not be called in managed mode.\")\n\t}\n\treturn db.newStream()\n}\n\n// NewStreamAt creates a new Stream at a particular timestamp. Should only be used with managed DB.\nfunc (db *DB) NewStreamAt(readTs uint64) *Stream {\n\tif !db.opt.managedTxns {\n\t\tpanic(\"This API can only be called in managed mode.\")\n\t}\n\tstream := db.newStream()\n\tstream.readTs = readTs\n\treturn stream\n}\n\nfunc BufferToKVList(buf *z.Buffer) (*pb.KVList, error) {\n\tvar list pb.KVList\n\terr := buf.SliceIterate(func(s []byte) error {\n\t\tkv := new(pb.KV)\n\t\tif err := proto.Unmarshal(s, kv); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlist.Kv = append(list.Kv, kv)\n\t\treturn nil\n\t})\n\treturn &list, err\n}","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/stream.go#L481-L517","documentation":"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.","triggerScenarios":"Calling db.NewStreamAt(readTs) on a DB opened with badger.Open (unmanaged), directly or via helpers like getSampleKeys/StreamDB that assume a managed DB.","commonSituations":"Mixing OpenManaged and Open across environments (test uses managed, prod does not); using managed-only restore/stream utilities against a normal DB instance.","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"],"exampleFix":"// before\ndb, _ := badger.Open(opts) // unmanaged\nstream := db.NewStreamAt(ts) // panics\n// after\ndb, _ := badger.OpenManaged(opts)\nstream := db.NewStreamAt(db.MaxVersion())","handlingStrategy":"try-catch","validationCode":"func canUseNewStreamAt(db *badger.DB) bool { return isManagedDB(db) } // true only when opened via OpenManaged / WithManagedTxns(true)","typeGuard":"func recoverPanicString(r interface{}) (string, bool) {\n    s, ok := r.(string)\n    return s, ok\n}","tryCatchPattern":"func safeNewStreamAt(db *badger.DB, readTs uint64) (s *badger.Stream, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            if msg, ok := r.(string); ok && strings.Contains(msg, \"managed mode\") {\n                err = errors.New(\"db not in managed mode: use NewStream()\")\n                return\n            }\n            panic(r)\n        }\n    }()\n    s = db.NewStreamAt(readTs)\n    return\n}","preventionTips":["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"],"tags":["badger","panic","managed-mode","api-misuse"],"backgroundTag":"api-called-in-wrong-mode","analyzedSha":"2a001d466f6b71a917319a1db41f99860e16e269","analyzedAt":"2026-09-05T13:00:02.264Z","contentChangedAt":"2026-09-05T13:00:02.264Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}