{"record":{"id":"60b34eabd1d3dc9c","repo":"dgraph-io/badger","slug":"update-can-only-be-used-with-manageddb-false","errorCode":null,"errorMessage":"Update can only be used with managedDB=false.","messagePattern":"Update can only be used with managedDB=false\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"txn.go","lineNumber":811,"sourceCode":"\tif db.opt.managedTxns {\n\t\ttxn = db.NewTransactionAt(math.MaxUint64, false)\n\t} else {\n\t\ttxn = db.NewTransaction(false)\n\t}\n\tdefer txn.Discard()\n\n\treturn fn(txn)\n}\n\n// Update executes a function, creating and managing a read-write transaction\n// for the user. Error returned by the function is relayed by the Update method.\n// Update cannot be used with managed transactions.\nfunc (db *DB) Update(fn func(txn *Txn) error) error {\n\tif db.IsClosed() {\n\t\treturn ErrDBClosed\n\t}\n\tif db.opt.managedTxns {\n\t\tpanic(\"Update can only be used with managedDB=false.\")\n\t}\n\ttxn := db.NewTransaction(true)\n\tdefer txn.Discard()\n\n\tif err := fn(txn); err != nil {\n\t\treturn err\n\t}\n\n\treturn txn.Commit()\n}\n","sourceCodeStart":793,"sourceCodeEnd":822,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/txn.go#L793-L822","documentation":"db.Update is the user-mode (non-managed) transaction helper. When the DB was opened with WithManagedTransactions(true), Badger requires managed APIs (NewTransactionAt/CommitAt) and deliberately panics if Update is called, since implicit commit semantics conflict with managed version control. The check happens before any transaction is created.","triggerScenarios":"Opening DB with WithManagedTransactions(true) and then calling db.Update(fn) (or db.View with the same pattern); caller of Update such as a helper like moveMoney or a subscription handler (updateLease) that assumes user mode.","commonSituations":"Enabling managed mode to control read/write timestamps (e.g. Dgraph integration, replica read streams) while leftover application code still uses Update/View helpers.","solutions":["Replace db.Update with db.NewTransactionAt(readonly=false) + explicit txn.CommitAt(ts, cb)","Or open a second DB instance without WithManagedTransactions for user-mode code","Audit call sites (populateEntries, updateLease, etc.) and convert each Update to the managed pattern"],"exampleFix":"// before\ndb.Update(func(txn *Txn) error { return txn.Set(key, val) })\n// after\ntxn := db.NewTransactionAt(writeTs, true)\nif err := txn.Set(key, val); err != nil { txn.Discard(); return err }\nreturn txn.CommitAt(writeTs, nil)","handlingStrategy":"validation","validationCode":"if db.Opt().managedTxns == false {\n    return db.Update(fn)\n}\ntxn := db.NewTransactionAt(writeTs, true)\nerr := fn(txn)\nif err == nil { err = txn.CommitAt(writeTs, nil) } else { txn.Discard() }\nreturn err","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Track managed mode as a config flag and branch transaction helpers on it","Write managed-mode wrappers (UpdateAt/ViewAt) so raw Update is never called","Search codebase for db.Update/View after enabling WithManagedTransactions"],"tags":["panic","managed-transactions","public-api","mode-mismatch"],"backgroundTag":"managed-mode-api-mismatch","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"}