dgraph-io/badger · error
ErrGCInReadOnlyMode
ErrGCInReadOnlyMode
Error message
Cannot run value log GC when DB is opened in ReadOnly mode
What it means
ErrGCInReadOnlyMode is a sentinel error returned by DB.RunValueLogGC when the badger DB was opened with the ReadOnly option set to true. Garbage collection rewrites and truncates value log files, a write operation that a read-only DB cannot perform, so the call is rejected immediately after the InMemory check in RunValueLogGC (db.go:1309).
Source
Thrown at errors.go:113
// ErrNilCallback is returned when subscriber's callback is nil.
ErrNilCallback = stderrors.New("Callback cannot be nil")
// ErrEncryptionKeyMismatch is returned when the storage key is not
// matched with the key previously given.
ErrEncryptionKeyMismatch = stderrors.New("Encryption key mismatch")
// ErrInvalidDataKeyID is returned if the datakey id is invalid.
ErrInvalidDataKeyID = stderrors.New("Invalid datakey id")
// ErrInvalidEncryptionKey is returned if length of encryption keys is invalid.
ErrInvalidEncryptionKey = stderrors.New("Encryption key's length should be" +
"either 16, 24, or 32 bytes")
// ErrGCInMemoryMode is returned when db.RunValueLogGC is called in in-memory mode.
ErrGCInMemoryMode = stderrors.New("Cannot run value log GC when DB is opened in InMemory mode")
// ErrGCInReadOnlyMode is returned when db.RunValueLogGC is called in read-only mode.
ErrGCInReadOnlyMode = stderrors.New("Cannot run value log GC when DB is opened in ReadOnly mode")
// ErrDBClosed is returned when a get operation is performed after closing the DB.
ErrDBClosed = stderrors.New("DB Closed")
)
View on GitHub (pinned to 2a001d466f)
Solutions
- Skip RunValueLogGC entirely for DBs opened in ReadOnly mode.
- Run value log GC on the writable primary instance instead.
- If the directory must be writable again, reopen the DB without WithReadOnly(true).
- Treat the error as a no-op: if errors.Is(err, badger.ErrGCInReadOnlyMode), log and continue.
Example fix
// before
err := db.RunValueLogGC(0.5)
// after
if !opts.ReadOnly {
if err := db.RunValueLogGC(0.5); err != nil && !errors.Is(err, badger.ErrGCInReadOnlyMode) {
return err
}
} Defensive patterns
Strategy: validation
Validate before calling
func shouldRunGC(db *badger.DB, readOnly bool) bool {
return !readOnly // GC needs write access to value log files
}
// call site:
if !readOnly {
if err := db.RunValueLogGC(0.5); err != nil { ... }
} Type guard
func canRunValueLogGC(opt badger.Options) bool {
return !opt.ReadOnly && !opt.InMemory
} Try / catch
if err := db.RunValueLogGC(0.5); err != nil {
if errors.Is(err, badger.ErrGCInReadOnlyMode) {
return nil // expected on read-only DBs, skip GC
}
return err
} Prevention
- Track the ReadOnly flag from options wherever GC maintenance is scheduled.
- Run value log GC only on writable primaries, never on read-only replicas.
- On read-only filesystems, treat all write-maintenance as skipped by design.
- Use errors.Is against badger.ErrGCInReadOnlyMode instead of comparing messages.
When it happens
Trigger: Calling db.RunValueLogGC(discardRatio) on a DB opened with badger.Open(opts.WithReadOnly(true)) — e.g. a replica or a database opened for inspection on read-only storage.
Common situations: Opening a badger directory on a read-only filesystem or a secondary/read-only replica for analytics, then reusing maintenance code that runs GC; test code like db_test.go:1794 that explicitly exercises this path.
Related errors
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/0eb7db1df206b40d.
Report an issue: GitHub.