benbjohnson/litestream · error
l0 retention must not be negative
Error message
l0 retention must not be negative
What it means
Sentinel error ErrInvalidL0Retention is returned by Config.Validate when l0-retention is configured with a negative value. Unlike most intervals, zero is allowed for L0 retention (meaning effectively no retention), but a negative duration is nonsensical and rejected. Wrapped in ConfigValidationError with Field "l0-retention".
Source
Thrown at cmd/litestream/main.go:57
// Version is set via -ldflags "-X main.Version=..." on release and Makefile
// builds; otherwise it is resolved from embedded VCS build info at startup.
var Version = defaultVersion
func init() {
bi, _ := debug.ReadBuildInfo()
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)View on GitHub (pinned to 4ed7a308f6)
Solutions
- Set l0-retention to a non-negative duration (0 is permitted, e.g. "24h" for a day of L0 retention).
- If you wanted to disable L0 retention, use 0 rather than a negative value.
- Check for arithmetic or sign errors in whatever computes the value.
Example fix
# before l0-retention: -5m # after l0-retention: 24h
Defensive patterns
Strategy: validation
Validate before calling
if cfg.L0Retention != nil && *cfg.L0Retention < 0 {
return errors.New("l0-retention must be >= 0")
} Try / catch
if err := cfg.Validate(); err != nil {
var ve *main.ConfigValidationError
if errors.As(err, &ve) && errors.Is(ve.Err, main.ErrInvalidL0Retention) {
return fmt.Errorf("l0-retention %v is negative", ve.Value)
}
return err
} Prevention
- Remember 0 is legal for l0-retention; only negatives fail — use 0 to disable.
- Double-check signs when computing retention durations programmatically.
- Validate configs before deployment.
When it happens
Trigger: Setting l0-retention to a negative duration in the top-level config (e.g. l0-retention: "-5m") and running Validate.
Common situations: Sign typo when writing the duration; a computed value where a subtraction went negative; misreading docs that allow 0 but not negatives.
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
- snapshot retention must be greater than 0
- l0 retention check interval must be greater than 0
- snapshot interval must be greater than 0
- compaction interval must be greater than 0
- sync interval must be greater than 0
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/9409735768e515f6.
Report an issue: GitHub.