benbjohnson/litestream · error
database config #%d: duplicate path %q (already used by data
Error message
database config #%d: duplicate path %q (already used by database config #%d); each database can be listed only once
What it means
During config validation, litestream rejects a config file that lists the same database path in two `database` entries. The metadata directory is derived from the database path, so duplicates would share one metadata dir and race on the same LTX temp files. The message names both offending config indexes (1-based) and the duplicated path.
Source
Thrown at cmd/litestream/main.go:508
// Validate database configs
seenPaths := make(map[string]int) // cleaned path -> 1-based config index
for idx, db := range c.DBs {
// Validate that either path or dir is specified, but not both
if db.Path != "" && db.Dir != "" {
return fmt.Errorf("database config #%d: cannot specify both 'path' and 'dir'", idx+1)
}
if db.Path == "" && db.Dir == "" {
return fmt.Errorf("database config #%d: must specify either 'path' or 'dir'", idx+1)
}
// 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)
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Remove the duplicate database entry identified by the two config indexes in the message, keeping the one with the correct replica settings.
- If you intended different settings for the same DB, litestream supports a single replica per database — merge the settings into one entry.
- Normalize paths (no `.`/`..` segments) so matching entries are obvious; note the check compares filepath.Clean'd paths.
- Run `litestream -config <file> ...` again after editing to confirm validation passes.
Example fix
# before (litestream.yml)
dbs:
- path: /var/lib/app.db
replicas:
- url: s3://bucket/app
- path: /var/lib/app.db
replicas:
- url: s3://bucket/app2
# after
dbs:
- path: /var/lib/app.db
replicas:
- url: s3://bucket/app Defensive patterns
Strategy: validation
Validate before calling
# lint config before deploy: no duplicate db paths paths=$(yq '.dbs[].path' litestream.yml | xargs -n1 realpath -e | sort) if [ "$(echo "$paths" | sort -u | wc -l)" != "$(echo "$paths" | wc -l)" ]; then echo 'duplicate database path in config'; exit 1 fi
Try / catch
if err := cmd.Run(); err != nil {
var cfgErr *ConfigError // or match on 'duplicate path'
if strings.Contains(err.Error(), "duplicate path") {
log.Fatal("fix litestream.yml: remove the duplicated database entry named in the error")
}
log.Fatal(err)
} Prevention
- Keep one entry per database; a database supports exactly one replica listed once.
- When merging config fragments, diff paths before concatenating dbs lists.
- Write canonical absolute paths (no ./.. segments) so duplicates are visible.
- Validate configs in CI before deployment.
When it happens
Trigger: ParseConfig followed by Validate on a YAML config containing two `dbs:` entries with identical `path:` values (after filepath.Clean normalization), e.g. `/var/lib/app.db` listed twice, or the same path written with redundant segments like `/var/lib/./app.db`.
Common situations: Merging config snippets from two files or teammates and accidentally duplicating a db entry; copy-pasting an entry to add a second replica but forgetting each database can have only one replica listed once; path aliases (symlink vs real path written differently but cleaning to the same key).
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- heartbeat URL must be a valid HTTP or HTTPS URL
- heartbeat interval must be at least 1 minute
- database config #%d: 'pattern' is required when using 'dir'
- database config #%d: 'watch' can only be enabled with a dire
- database config #%d: 'meta-dir' can only be used with a dire
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/fa8dbb02e6e5b0d1.
Report an issue: GitHub.