benbjohnson/litestream · error
heartbeat URL must be a valid HTTP or HTTPS URL
Error message
heartbeat URL must be a valid HTTP or HTTPS URL
What it means
ErrInvalidHeartbeatURL is returned by Config.Validate when the heartbeat-url config value is set but is not a parseable HTTP or HTTPS URL. Litestream sends periodic heartbeat pings to this URL, so a malformed value would silently break monitoring; validation rejects it up front via ConfigValidationError with Field "heartbeat-url".
Source
Thrown at cmd/litestream/main.go:61
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)
}
return fmt.Sprintf("%s: %v", e.Field, e.Err)
}
View on GitHub (pinned to 4ed7a308f6)
Solutions
- Prefix the URL with http:// or https:// in the config
- Verify the value with the URL parser you expect: it must parse and have Scheme http or https
- Remove heartbeat-url entirely if you do not want heartbeats
Example fix
# before heartbeat-url: monitoring.internal:8080/ping # after heartbeat-url: https://monitoring.internal:8080/ping
Defensive patterns
Strategy: validation
Validate before calling
func validHeartbeatURL(s string) bool {
u, err := url.Parse(s)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}
// call before writing config / at startup Prevention
- Always include an explicit http:// or https:// scheme in config URLs
- Lint config files for URL fields at deploy time
- Keep heartbeat URLs in one templated variable to avoid per-env typos
When it happens
Trigger: Setting heartbeat-url in the YAML config (or the c.HeartbeatURL field) to a value that fails isValidHeartbeatURL: a scheme-less host ("myhost/ping"), an unsupported scheme ("ftp://...", "tcp://..."), or a string that does not parse as a URL at all.
Common situations: Typos like heartbeat-url: myserver:8080/ping (missing scheme), copying an internal service URL that starts with a scheme other than http/https, or quoting issues in YAML that leave stray characters in the value.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- file replica path required
- bucket required for gs replica URL
- oss: invalid url scheme
- replica url scheme required: %s
- host required for webdav replica URL
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/4b6c3fec40b6ef5e.
Report an issue: GitHub.