benbjohnson/litestream · error
database config #%d: 'watch' can only be enabled with a dire
Error message
database config #%d: 'watch' can only be enabled with a directory
What it means
Validate() in cmd/litestream/main.go rejects a database config entry where 'watch: true' is set but no 'dir' is configured. Watch-mode file monitoring only works for directory-based replication, where Litestream scans a directory for SQLite databases; for a single-database 'path' config it is meaningless. The check fires per database entry during config parsing.
Source
Thrown at cmd/litestream/main.go:518
}
// Reject the same database path listed twice. The metadata directory is
// derived from the path, so two entries would share it and race on the
// same LTX temp files.
if db.Path != "" {
key := filepath.Clean(db.Path)
if first, ok := seenPaths[key]; ok {
return fmt.Errorf("database config #%d: duplicate path %q (already used by database config #%d); each database can be listed only once", idx+1, db.Path, first)
}
seenPaths[key] = idx + 1
}
// When using dir, pattern must be specified
if db.Dir != "" && db.Pattern == "" {
return fmt.Errorf("database config #%d: 'pattern' is required when using 'dir'", idx+1)
}
if db.Watch && db.Dir == "" {
return fmt.Errorf("database config #%d: 'watch' can only be enabled with a directory", idx+1)
}
if db.MetaDir != nil && db.Dir == "" {
return fmt.Errorf("database config #%d: 'meta-dir' can only be used with a directory", idx+1)
}
if db.MetaPath != nil && db.MetaDir != nil {
return fmt.Errorf("database config #%d: cannot specify both 'meta-path' and 'meta-dir'", idx+1)
}
// Use path or dir for identifying the config in error messages
dbIdentifier := db.Path
if dbIdentifier == "" {
dbIdentifier = db.Dir
}
if db.Snapshot.Interval != nil && *db.Snapshot.Interval <= 0 {
return &ConfigValidationError{
Err: ErrInvalidSnapshotInterval,
Field: fmt.Sprintf("dbs[%s].snapshot.interval", dbIdentifier),View on GitHub (pinned to 4ed7a308f6)
Solutions
- Remove `watch: true` from the single-database config entry, or
- Convert the entry to directory-based replication by setting `dir:` (and the required `pattern:`) instead of `path:`, keeping `watch: true`.
- If periodic monitoring is desired for a single DB, rely on the default monitor interval; watch is not supported for path-based configs.
Example fix
# before
databases:
- path: /var/db/app.db
watch: true
# after (option A: drop watch)
databases:
- path: /var/db/app.db
# after (option B: use dir)
databases:
- dir: /var/db
pattern: "*.db"
watch: true Defensive patterns
Strategy: validation
Validate before calling
for i, db := range cfg.Databases {
if db.Watch && db.Dir == "" {
return fmt.Errorf("db #%d: 'watch' requires 'dir'", i+1)
}
} Prevention
- Only set watch:true on directory-based entries
- Lint configs against the DBConfig schema before deploy
- Test configs with `litestream -config file.yml` in CI
When it happens
Trigger: Running `litestream` (or ParseConfig -> Validate) with a YAML/JSON config where a databases[] entry has `watch: true` but only `path:` set (no `dir:`).
Common situations: User copies watch settings from a directory-replication example into a single-DB config; user misunderstands 'watch' as a general polling option and enables it on a path-based database entry.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- database config #%d: 'meta-dir' can only be used with a dire
- database config #%d: cannot specify both 'meta-path' and 'me
- 'meta-dir' can only be used with a directory
- directory path is required for directory replication
- pattern is required for directory replication
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/d6796f675efa2e10.
Report an issue: GitHub.