benbjohnson/litestream · error

heartbeat interval must be at least 1 minute

Error message

heartbeat interval must be at least 1 minute

What it means

ErrInvalidHeartbeatInterval is returned by Config.Validate when heartbeat-interval is set below litestream.MinHeartbeatInterval (1 minute). Heartbeats are low-frequency liveness signals, so sub-minute intervals are rejected to avoid hammering the target endpoint.

Source

Thrown at cmd/litestream/main.go:62

	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)
	}
	return fmt.Sprintf("%s: %v", e.Field, e.Err)
}

func (e *ConfigValidationError) Unwrap() error {

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Set heartbeat-interval to at least 1m (e.g. 5m)
  2. Check the duration unit suffix — Go durations need s/m/h, a bare number is nanoseconds
  3. Remove heartbeat-interval to use the default interval

Example fix

# before
heartbeat-interval: 30s
# after
heartbeat-interval: 5m
Defensive patterns

Strategy: validation

Validate before calling

if hb != "" {
    d, err := time.ParseDuration(hb)
    if err != nil || d < time.Minute {
        return fmt.Errorf("heartbeat-interval must be >= 1m, got %q", hb)
    }
}

Prevention

When it happens

Trigger: Setting heartbeat-interval in the config to a duration smaller than 1m (e.g. 30s, 10s, 500ms) — detected in Validate via *c.HeartbeatInterval < litestream.MinHeartbeatInterval.

Common situations: Users assuming heartbeat frequency should match sync-interval granularity and writing "30s", or misparsing the duration unit ("1" meaning 1 minute but parsed as 1 nanosecond).

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


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