dgraph-io/badger · error
Cannot flatten in read-only mode.
Error message
Cannot flatten in read-only mode.
What it means
Returned by DB.Flatten when the database is in read-only mode. Flatten forces compactions across the LSM tree so all tables land on one level, and compaction writes new tables and rewrites the MANIFEST — operations that a read-only database cannot perform, hence the guard rejects the call.
Source
Thrown at db.go:1665
func (db *DB) startMemoryFlush() {
// Start memory fluhser.
if db.closers.memtable != nil {
db.flushChan = make(chan *memTable, db.opt.NumMemtables)
db.closers.memtable = z.NewCloser(1)
go func() {
db.flushMemtable(db.closers.memtable)
}()
}
}
// Flatten can be used to force compactions on the LSM tree so all the tables fall on the same
// level. This ensures that all the versions of keys are colocated and not split across multiple
// levels, which is necessary after a restore from backup. During Flatten, live compactions are
// stopped. Ideally, no writes are going on during Flatten. Otherwise, it would create competition
// between flattening the tree and new tables being created at level zero.
func (db *DB) Flatten(workers int) error {
if db.opt.ReadOnly {
panic("Cannot flatten in read-only mode.")
}
db.stopCompactions()
defer db.startCompactions()
compactAway := func(cp compactionPriority) error {
db.opt.Infof("Attempting to compact with %+v\n", cp)
errCh := make(chan error, 1)
for i := 0; i < workers; i++ {
go func() {
errCh <- db.lc.doCompact(175, cp)
}()
}
var success int
var rerr error
for i := 0; i < workers; i++ {
err := <-errCh
if err != nil {View on GitHub (pinned to 2a001d466f)
Solutions
- Open the DB in write mode before calling Flatten
- Do Flatten on the primary/writable instance, not read-only replicas
- Check db.opt.ReadOnly before calling Flatten
Example fix
// before opt.ReadOnly = true db, _ := badger.Open(opt) db.Flatten(4) // panics // after opt.ReadOnly = false // writable copy db, _ := badger.Open(opt) db.Flatten(4)
Defensive patterns
Strategy: validation
Validate before calling
if db.opt.ReadOnly { return errors.New("Flatten unavailable in read-only mode") } Try / catch
defer func() {
if r := recover(); r != nil {
if strings.Contains(fmt.Sprint(r), "Cannot flatten in read-only") { /* schedule on writable node */ }
}
}() Prevention
- Run maintenance (Flatten/DropAll) only on writable instances
- Check opt.ReadOnly before administrative operations
- Recover around admin ops so config panics fail gracefully
When it happens
Trigger: Calling db.Flatten(workers) on a DB opened with badger.ReadOnly, typically after a restore or on a read-only replica.
Common situations: Running flatten/defrag maintenance scripts against a read-only mounted directory; read-only disaster-recovery nodes.
Related errors
- Cannot use GetSequence in read-only mode.
- Attempting to drop data in read-only mode.
- Cannot ban namespace in read-only mode.
- ErrReadOnlyTxn
- ErrWindowsNotSupported
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/7c7fca9daa62c39d.
Report an issue: GitHub.