benbjohnson/litestream · error
database config required
Error message
database config required
What it means
NewDirectoryMonitor constructs a monitor for directory-based replication and requires a non-nil *DBConfig describing the database directory to watch. This error is returned immediately when the dbc parameter is nil, because without a DBConfig the monitor cannot determine which directory to watch or which database to manage. It is a programmer-error guard against calling the constructor with incomplete arguments.
Source
Thrown at cmd/litestream/directory_watcher.go:49
cancel context.CancelFunc
logger *slog.Logger
mu sync.Mutex
dbs map[string]*litestream.DB
watchedDirs map[string]struct{}
// Only accessed from the run() goroutine, so no mutex is needed.
pendingEvents map[string]fsnotify.Op
debounceActive bool
wg sync.WaitGroup
}
// NewDirectoryMonitor returns a new monitor for directory-based replication.
func NewDirectoryMonitor(ctx context.Context, store *litestream.Store, dbc *DBConfig, existing []*litestream.DB) (*DirectoryMonitor, error) {
if dbc == nil {
return nil, errors.New("database config required")
}
if store == nil {
return nil, errors.New("store required")
}
dirPath, err := expand(dbc.Dir)
if err != nil {
return nil, err
}
if _, err := os.Stat(dirPath); err != nil {
return nil, err
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}View on GitHub (pinned to 4ed7a308f6)
Solutions
- Ensure the *DBConfig passed to NewDirectoryMonitor is non-nil; construct one with at least Dir set to the database directory path.
- Check upstream config parsing (where DBConfig is built) to see why it produced nil; log/skip nil entries before calling NewDirectoryMonitor.
- If the config has no directory-based DB, do not call NewDirectoryMonitor at all instead of passing nil.
Example fix
// before
mon, err := NewDirectoryMonitor(ctx, store, cfg.DB, existing)
// after
if cfg.DB == nil {
return fmt.Errorf("no db config configured for directory monitor")
}
mon, err := NewDirectoryMonitor(ctx, store, cfg.DB, existing) Defensive patterns
Strategy: type-guard
Validate before calling
if dbc == nil {
return errors.New("directory monitor requires a DBConfig with Dir set")
}
if dbc.Dir == "" {
return errors.New("DBConfig.Dir must be set")
} Type guard
func validMonitorArgs(store *litestream.Store, dbc *litestream.DBConfig) bool {
return store != nil && dbc != nil && dbc.Dir != ""
} Try / catch
mon, err := litestream.NewDirectoryMonitor(ctx, store, dbc, existing)
if err != nil {
if err.Error() == "database config required" {
// dbc was nil: fix config loading before retry
}
return fmt.Errorf("directory monitor: %w", err)
} Prevention
- Never pass config structs that may be nil; build them unconditionally or skip the monitor entirely.
- Centralize DBConfig construction in one function that always returns non-nil or an error.
- Check the return error of every constructor at startup and fail fast.
When it happens
Trigger: Calling litestream.NewDirectoryMonitor(ctx, store, nil, existing) with a nil *DBConfig, e.g. when DB config parsing silently produced no config or a loop over configs skipped initialization and passed a nil entry.
Common situations: Building a custom embedding of litestream where DBConfig is conditionally populated (e.g. only set when a 'dir' key exists in user config) and the nil case is passed through; refactoring code that used to construct DBConfig unconditionally; misparsing TOML/YAML config so the dbs entry yields a nil config.
Related errors
- store required
- snapshot interval must be greater than 0
- snapshot retention must be greater than 0
- compaction interval must be greater than 0
- sync interval must be greater than 0
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/685d62059258bbda.
Report an issue: GitHub.