{"record":{"id":"28cbf05cd8e3d19f","repo":"dgraph-io/badger","slug":"cannot-use-newtransactionat-with-manageddb-false","errorCode":null,"errorMessage":"Cannot use NewTransactionAt with managedDB=false. Use NewTransaction instead.","messagePattern":"Cannot use NewTransactionAt with managedDB=false\\. Use NewTransaction instead\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"managed_db.go","lineNumber":25,"sourceCode":"\n// OpenManaged returns a new DB, which allows more control over setting\n// transaction timestamps, aka managed mode.\n//\n// This is only useful for databases built on top of Badger (like Dgraph), and\n// can be ignored by most users.\nfunc OpenManaged(opts Options) (*DB, error) {\n\topts.managedTxns = true\n\treturn Open(opts)\n}\n\n// NewTransactionAt follows the same logic as DB.NewTransaction(), but uses the\n// provided read timestamp.\n//\n// This is only useful for databases built on top of Badger (like Dgraph), and\n// can be ignored by most users.\nfunc (db *DB) NewTransactionAt(readTs uint64, update bool) *Txn {\n\tif !db.opt.managedTxns {\n\t\tpanic(\"Cannot use NewTransactionAt with managedDB=false. Use NewTransaction instead.\")\n\t}\n\ttxn := db.newTransaction(update, true)\n\ttxn.readTs = readTs\n\treturn txn\n}\n\n// NewWriteBatchAt is similar to NewWriteBatch but it allows user to set the commit timestamp.\n// NewWriteBatchAt is supposed to be used only in the managed mode.\nfunc (db *DB) NewWriteBatchAt(commitTs uint64) *WriteBatch {\n\tif !db.opt.managedTxns {\n\t\tpanic(\"cannot use NewWriteBatchAt with managedDB=false. Use NewWriteBatch instead\")\n\t}\n\n\twb := db.newWriteBatch(true)\n\twb.commitTs = commitTs\n\twb.txn.commitTs = commitTs\n\treturn wb\n}","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/managed_db.go#L7-L43","documentation":"This panic is thrown by Badger's DB.NewTransactionAt when the database was opened without managed transaction mode (badger.DefaultOptions has managedDb=false / WithManagedTxns(false)). NewTransactionAt exists only for databases layered on Badger (e.g. Dgraph) that supply their own read timestamps; regular users must use NewTransaction. The library panics instead of returning an error because this is a programming/API-misuse error detected at the call site.","triggerScenarios":"Calling db.NewTransactionAt(readTs, update) on a DB opened with managedTxns disabled (the default). Callers seen in practice: compareTwo, fullScanDB, showKeysStats, numKeysManaged, produceKVs — any tool code that assumes managed mode but opened the DB with plain options.","commonSituations":"A developer copies code from Dgraph or a managed-mode example without switching to WithManagedTxns(true) when opening the DB; a utility written for managed DBs is pointed at a normal application DB; options are refactored and the managed flag is dropped.","solutions":["Open the DB with WithManagedTxns(true): opts := badger.DefaultOptions(dir).WithManagedTxns(true); db, err := badger.Open(opts).","If managed mode is not needed, replace NewTransactionAt(readTs, update) with db.NewTransaction(update) and drop the explicit readTs.","Centralize DB opening in one helper so the managed flag and the At-style APIs stay consistent.","Wrap the call in a function with defer/recover if you must probe behavior, though fixing the options is the real fix."],"exampleFix":"// before\nopts := badger.DefaultOptions(dir)\ndb, _ := badger.Open(opts)\ntxn := db.NewTransactionAt(100, true)\n// after\nopts := badger.DefaultOptions(dir).WithManagedTxns(true)\ndb, _ := badger.Open(opts)\ntxn := db.NewTransactionAt(100, true)\n// ...or, without managed mode:\ntxn := db.NewTransaction(true)","handlingStrategy":"validation","validationCode":"if !db.Opts().ManagedTxns { // or track the option you passed to badger.Open\n    txn := db.NewTransaction(update)\n} else {\n    txn := db.NewTransactionAt(readTs, update)\n}","typeGuard":"func isManagedDB(db *badger.DB, openedManaged bool) bool { return openedManaged }","tryCatchPattern":"func safeNewTransactionAt(db *badger.DB, readTs uint64, update bool) (txn *badger.Txn, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"NewTransactionAt requires managed mode: %v\", r)\n        }\n    }()\n    txn = db.NewTransactionAt(readTs, update)\n    return\n}","preventionTips":["Always set WithManagedTxns(true) in the single shared DB-open helper if any code uses At-style APIs","Grep the codebase for NewTransactionAt/CommitAt/SetDiscardTs and verify each DB handle is opened in managed mode","Prefer NewTransaction/NewWriteBatch unless you genuinely manage timestamps (e.g. building on Badger like Dgraph)","Add a startup assertion that logs whether the DB is in managed mode before running timestamp-dependent tooling"],"tags":["go","badger","managed-transactions","panic","api-misuse"],"backgroundTag":"managed-mode-required","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"}