{"record":{"id":"5d403ae52d9b6a1c","repo":"dgraph-io/badger","slug":"cannot-use-setdiscardts-with-manageddb-false","errorCode":null,"errorMessage":"Cannot use SetDiscardTs with managedDB=false.","messagePattern":"Cannot use SetDiscardTs with managedDB=false\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"managed_db.go","lineNumber":75,"sourceCode":"// can be ignored by most users.\nfunc (txn *Txn) CommitAt(commitTs uint64, callback func(error)) error {\n\tif !txn.db.opt.managedTxns {\n\t\tpanic(\"Cannot use CommitAt with managedDB=false. Use Commit instead.\")\n\t}\n\ttxn.commitTs = commitTs\n\tif callback == nil {\n\t\treturn txn.Commit()\n\t}\n\ttxn.CommitWith(callback)\n\treturn nil\n}\n\n// SetDiscardTs sets a timestamp at or below which, any invalid or deleted\n// versions can be discarded from the LSM tree, and thence from the value log to\n// reclaim disk space. Can only be used with managed transactions.\nfunc (db *DB) SetDiscardTs(ts uint64) {\n\tif !db.opt.managedTxns {\n\t\tpanic(\"Cannot use SetDiscardTs with managedDB=false.\")\n\t}\n\tdb.orc.setDiscardTs(ts)\n}\n","sourceCodeStart":57,"sourceCodeEnd":79,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/managed_db.go#L57-L79","documentation":"DB.SetDiscardTs declares a timestamp below which invalid/deleted versions may be garbage-collected from the LSM tree and value log. Because this affects timestamp bookkeeping, it is only valid with managed transactions; the library panics if db.opt.managedTxns is false. Nothing is applied to db.orc (oracle) when the guard fires.","triggerScenarios":"Calling db.SetDiscardTs(ts) on a DB opened without WithManagedTxns(true). The panic is raised at managed_db.go:75 before db.orc.setDiscardTs(ts) runs, so no GC watermark is changed.","commonSituations":"Running manual or scripted GC/compaction maintenance copied from managed-mode tooling; an operator applying Dgraph-style cleanup to a plain application DB; maintenance scripts that were written against a managed replica pointed at a normal DB file.","solutions":["Open the DB with WithManagedTxns(true) before calling SetDiscardTs.","If you cannot use managed mode, do not set a discard timestamp manually; rely on Badger's default garbage collection (db.RunValueLogGC with appropriate thresholds).","Restrict SetDiscardTs to dedicated maintenance code paths that construct their own managed-mode DB handle.","Document that discard-ts maintenance requires managed mode so operators don't reuse the script on ordinary DBs."],"exampleFix":"// before\nopts := badger.DefaultOptions(dir)\ndb, _ := badger.Open(opts)\ndb.SetDiscardTs(1000)\n// after\nopts := badger.DefaultOptions(dir).WithManagedTxns(true)\ndb, _ := badger.Open(opts)\ndb.SetDiscardTs(1000)","handlingStrategy":"validation","validationCode":"if managedMode {\n    db.SetDiscardTs(ts)\n} else {\n    // rely on default GC: db.RunValueLogGC(0.5) etc.\n}","typeGuard":"func discardTsSupported(managedTxns bool) bool { return managedTxns }","tryCatchPattern":"func safeSetDiscardTs(db *badger.DB, ts uint64) (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"SetDiscardTs requires managed mode: %v\", r)\n        }\n    }()\n    db.SetDiscardTs(ts)\n    return\n}","preventionTips":["Invoke SetDiscardTs only from maintenance code that opens its own managed-mode handle","In non-managed apps, use db.RunValueLogGC for space reclamation instead of manual discard timestamps","Verify the discard timestamp never exceeds values still visible to readers","Keep GC/maintenance scripts and application DB-open options documented together to avoid mode mismatches"],"tags":["go","badger","managed-transactions","garbage-collection","panic"],"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"}