dgraph-io/badger · error
ErrDBClosed
ErrDBClosed
Error message
DB Closed
What it means
ErrDBClosed is a sentinel error returned when a data operation is attempted after DB.Close() has completed. DB.get (db.go:791) returns it whenever db.IsClosed() is true, and the iterator code panics with it (iterator.go:464) if an iterator is used after close. The public View/Update transaction helpers surface it to callers of Get/Iterate after shutdown.
Source
Thrown at errors.go:116
// 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
- Ensure Close() is the last operation: cancel/clean up all goroutines, wait for in-flight requests (WaitGroup), then close.
- Guard every access with db.IsClosed() before View/Update, or track closed state in application code.
- Use errors.Is(err, badger.ErrDBClosed) to distinguish shutdown races from real failures and fail gracefully.
- Fix double-close ordering bugs: never issue reads after a deferred Close in the same call path.
Example fix
// before
go refreshCache(db)
db.Close()
// after
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); refreshCache(db) }()
wg.Wait()
db.Close()
// and in read paths:
if db.IsClosed() { return badger.ErrDBClosed } Defensive patterns
Strategy: try-catch
Validate before calling
if db.IsClosed() {
return badger.ErrDBClosed // or skip the read
}
err := db.View(func(txn *badger.Txn) error { ... }) Type guard
func (w *SafeDB) usable() bool {
w.mu.RLock()
defer w.mu.RUnlock()
return !w.db.IsClosed()
} Try / catch
err := db.View(func(txn *badger.Txn) error { ... })
if errors.Is(err, badger.ErrDBClosed) {
// DB is shutting down: log, drop the request or return a clean shutdown code
return nil
} Prevention
- Stop all background goroutines and wait for in-flight requests (WaitGroup/errgroup) before calling Close().
- Never read from a DB after a deferred Close in the same function scope.
- Wrap *badger.DB in a wrapper exposing Close once and rejecting later operations (sync.Once + closed flag).
- Check db.IsClosed() at the top of long-running loops that read from badger.
- Use errors.Is(err, badger.ErrDBClosed) to distinguish shutdown races from real read failures.
When it happens
Trigger: Calling db.View(), db.Update(), txn.Get() or creating/using an iterator after db.Close() has returned; also background goroutines or deferred callbacks that outlive Close and keep touching the DB.
Common situations: Application shutdown racing with in-flight request handlers; background cache-refresh goroutines not cancelled before Close; accidental double-close followed by a read; tests calling View after Close.
Related errors
AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05).
Data as JSON: /api/errors/c754e202e27a9dc8.
Report an issue: GitHub.