{"record":{"id":"cc53af96c505c12b","repo":"benbjohnson/litestream","slug":"heartbeat-interval-must-be-at-least-1-minute","errorCode":null,"errorMessage":"heartbeat interval must be at least 1 minute","messagePattern":"heartbeat interval must be at least 1 minute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/main.go","lineNumber":62,"sourceCode":"\tbi, _ := debug.ReadBuildInfo()\n\tVersion = resolveVersion(Version, bi)\n}\n\n// errStop is a terminal error for indicating program should quit.\nvar errStop = errors.New(\"stop\")\n\n// Sentinel errors for configuration validation\nvar (\n\tErrInvalidSnapshotInterval         = errors.New(\"snapshot interval must be greater than 0\")\n\tErrInvalidSnapshotRetention        = errors.New(\"snapshot retention must be greater than 0\")\n\tErrInvalidCompactionInterval       = errors.New(\"compaction interval must be greater than 0\")\n\tErrInvalidSyncInterval             = errors.New(\"sync interval must be greater than 0\")\n\tErrInvalidL0Retention              = errors.New(\"l0 retention must not be negative\")\n\tErrInvalidL0RetentionCheckInterval = errors.New(\"l0 retention check interval must be greater than 0\")\n\tErrInvalidShutdownSyncTimeout      = errors.New(\"shutdown-sync-timeout must be >= 0\")\n\tErrInvalidShutdownSyncInterval     = errors.New(\"shutdown sync interval must be greater than 0\")\n\tErrInvalidHeartbeatURL             = errors.New(\"heartbeat URL must be a valid HTTP or HTTPS URL\")\n\tErrInvalidHeartbeatInterval        = errors.New(\"heartbeat interval must be at least 1 minute\")\n\tErrConfigFileNotFound              = errors.New(\"config file not found\")\n)\n\n// ConfigValidationError wraps a validation error with additional context\ntype ConfigValidationError struct {\n\tErr   error\n\tField string\n\tValue interface{}\n}\n\nfunc (e *ConfigValidationError) Error() string {\n\tif e.Value != nil {\n\t\treturn fmt.Sprintf(\"%s: %v (got %v)\", e.Field, e.Err, e.Value)\n\t}\n\treturn fmt.Sprintf(\"%s: %v\", e.Field, e.Err)\n}\n\nfunc (e *ConfigValidationError) Unwrap() error {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Set heartbeat-interval to at least 1m (e.g. 5m)","Check the duration unit suffix — Go durations need s/m/h, a bare number is nanoseconds","Remove heartbeat-interval to use the default interval"],"exampleFix":"# before\nheartbeat-interval: 30s\n# after\nheartbeat-interval: 5m","handlingStrategy":"validation","validationCode":"if hb != \"\" {\n    d, err := time.ParseDuration(hb)\n    if err != nil || d < time.Minute {\n        return fmt.Errorf(\"heartbeat-interval must be >= 1m, got %q\", hb)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember Go duration syntax requires units: write 5m not 300","Treat 1 minute as the floor when generating configs","Validate durations in CI before rolling out config changes"],"tags":["config","validation","duration"],"backgroundTag":"invalid-config-value","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}