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

  1. Remove the duplicate database entry identified by the two config indexes in the message, keeping the one with the correct replica settings.
  2. If you intended different settings for the same DB, litestream supports a single replica per database — merge the settings into one entry.
  3. Normalize paths (no `.`/`..` segments) so matching entries are obvious; note the check compares filepath.Clean'd paths.
  4. 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

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


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/fa8dbb02e6e5b0d1. Report an issue: GitHub.