{"record":{"id":"685d62059258bbda","repo":"benbjohnson/litestream","slug":"database-config-required","errorCode":null,"errorMessage":"database config required","messagePattern":"database config required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/directory_watcher.go","lineNumber":49,"sourceCode":"\tcancel  context.CancelFunc\n\n\tlogger *slog.Logger\n\n\tmu          sync.Mutex\n\tdbs         map[string]*litestream.DB\n\twatchedDirs map[string]struct{}\n\n\t// Only accessed from the run() goroutine, so no mutex is needed.\n\tpendingEvents  map[string]fsnotify.Op\n\tdebounceActive bool\n\n\twg sync.WaitGroup\n}\n\n// NewDirectoryMonitor returns a new monitor for directory-based replication.\nfunc NewDirectoryMonitor(ctx context.Context, store *litestream.Store, dbc *DBConfig, existing []*litestream.DB) (*DirectoryMonitor, error) {\n\tif dbc == nil {\n\t\treturn nil, errors.New(\"database config required\")\n\t}\n\tif store == nil {\n\t\treturn nil, errors.New(\"store required\")\n\t}\n\n\tdirPath, err := expand(dbc.Dir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif _, err := os.Stat(dirPath); err != nil {\n\t\treturn nil, err\n\t}\n\n\twatcher, err := fsnotify.NewWatcher()\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/directory_watcher.go#L31-L67","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmon, err := NewDirectoryMonitor(ctx, store, cfg.DB, existing)\n// after\nif cfg.DB == nil {\n    return fmt.Errorf(\"no db config configured for directory monitor\")\n}\nmon, err := NewDirectoryMonitor(ctx, store, cfg.DB, existing)","handlingStrategy":"type-guard","validationCode":"if dbc == nil {\n    return errors.New(\"directory monitor requires a DBConfig with Dir set\")\n}\nif dbc.Dir == \"\" {\n    return errors.New(\"DBConfig.Dir must be set\")\n}","typeGuard":"func validMonitorArgs(store *litestream.Store, dbc *litestream.DBConfig) bool {\n    return store != nil && dbc != nil && dbc.Dir != \"\"\n}","tryCatchPattern":"mon, err := litestream.NewDirectoryMonitor(ctx, store, dbc, existing)\nif err != nil {\n    if err.Error() == \"database config required\" {\n        // dbc was nil: fix config loading before retry\n    }\n    return fmt.Errorf(\"directory monitor: %w\", err)\n}","preventionTips":["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."],"tags":["go","configuration","nil-argument","directory-monitor"],"backgroundTag":"null-argument","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}