benbjohnson/litestream · error
config file not found
Error message
config file not found
What it means
ErrConfigFileNotFound is returned by OpenConfigFile when the config file passed via -config (or the default path) does not exist on disk. The filename is wrapped into the message with fmt.Errorf %w so errors.Is still matches.
Source
Thrown at cmd/litestream/main.go:63
Version = resolveVersion(Version, bi)
}
// errStop is a terminal error for indicating program should quit.
var errStop = errors.New("stop")
// Sentinel errors for configuration validation
var (
ErrInvalidSnapshotInterval = errors.New("snapshot interval must be greater than 0")
ErrInvalidSnapshotRetention = errors.New("snapshot retention must be greater than 0")
ErrInvalidCompactionInterval = errors.New("compaction interval must be greater than 0")
ErrInvalidSyncInterval = errors.New("sync interval must be greater than 0")
ErrInvalidL0Retention = errors.New("l0 retention must not be negative")
ErrInvalidL0RetentionCheckInterval = errors.New("l0 retention check interval must be greater than 0")
ErrInvalidShutdownSyncTimeout = errors.New("shutdown-sync-timeout must be >= 0")
ErrInvalidShutdownSyncInterval = errors.New("shutdown sync interval must be greater than 0")
ErrInvalidHeartbeatURL = errors.New("heartbeat URL must be a valid HTTP or HTTPS URL")
ErrInvalidHeartbeatInterval = errors.New("heartbeat interval must be at least 1 minute")
ErrConfigFileNotFound = errors.New("config file not found")
)
// ConfigValidationError wraps a validation error with additional context
type ConfigValidationError struct {
Err error
Field string
Value interface{}
}
func (e *ConfigValidationError) Error() string {
if e.Value != nil {
return fmt.Sprintf("%s: %v (got %v)", e.Field, e.Err, e.Value)
}
return fmt.Sprintf("%s: %v", e.Field, e.Err)
}
func (e *ConfigValidationError) Unwrap() error {
return e.ErrView on GitHub (pinned to 4ed7a308f6)
Solutions
- Check the path exists: ls the exact filename passed to -config
- Create the config file at DefaultConfigPath() if you intended default behavior
- Use an absolute path instead of a relative one
- Handle errors.Is(err, ErrConfigFileNotFound) in code that tolerates missing configs
Example fix
// before litestream -config litestream.yml // run from wrong cwd // after litestream -config /etc/litestream/litestream.yml
Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(cfgPath); os.IsNotExist(err) {
return fmt.Errorf("config file %s does not exist", cfgPath)
} Try / catch
if err := litestreamRun(ctx); err != nil {
if errors.Is(err, main.ErrConfigFileNotFound) {
slog.Error("config missing; generate one with 'litestream config'", "err", err)
os.Exit(1)
}
return err
} Prevention
- Use absolute paths for -config in systemd/containers
- Generate the default config before first run
- Check the working directory when using relative paths
When it happens
Trigger: Calling OpenConfigFile(filename) where os.Open returns os.IsNotExist — i.e. the -config path is wrong, the file was deleted, or the default config path is absent while no explicit path was given.
Common situations: Running litestream with -config /etc/litestream.yml on a fresh install where the file was never created, typo in the filename, or running from a different working directory with a relative path.
Understand the failure class
Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.
Related errors
- %w: %s
- cannot specify url & path for file replica
- file replica path required
- cannot create database from config: %w
- database not found in config: %s
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/3f9e6477639f738d.
Report an issue: GitHub.