benbjohnson/litestream · warning
unexpected status code: %d
Error message
unexpected status code: %d
What it means
HeartbeatClient.Ping() received an HTTP response but its status code was outside the 2xx range, so the heartbeat ping is considered failed. The error reports the exact status code returned by the heartbeat endpoint.
Source
Thrown at heartbeat.go:62
func (c *HeartbeatClient) Ping(ctx context.Context) error {
if c.URL == "" {
return nil
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.URL, nil)
if err != nil {
return fmt.Errorf("create request: %w", err)
}
resp, err := c.httpClient.Do(req)
if err != nil {
return fmt.Errorf("http request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
return nil
}
func (c *HeartbeatClient) ShouldPing() bool {
c.mu.Lock()
defer c.mu.Unlock()
return time.Since(c.lastPingAt) >= c.Interval
}
func (c *HeartbeatClient) LastPingAt() time.Time {
c.mu.Lock()
defer c.mu.Unlock()
return c.lastPingAt
}
func (c *HeartbeatClient) RecordPing() {View on GitHub (pinned to 4ed7a308f6)
Solutions
- Check the reported status code: 404 => recreate the check or update the URL in config; 401/403 => fix the ping key/credentials
- Verify the heartbeat check still exists in the monitoring service dashboard
- For 429, reduce ping frequency or check rate limits
- For 5xx, retry later — the heartbeat service is having issues
- Test the exact URL with `curl -i <url>` to reproduce the status code
Example fix
# before — stale check URL heartbeat: url: https://hc-ping.com/old-expired-uuid # after — recreated check heartbeat: url: https://hc-ping.com/new-active-uuid
Defensive patterns
Strategy: retry
Try / catch
if err := hb.Ping(ctx); err != nil {
var statusErr interface{ StatusCode() int }
// compare reported status code in the error text and alert on 4xx
logger.Warn("heartbeat non-2xx", "error", err)
} Prevention
- Pin heartbeat check URLs and rotate keys deliberately with config updates
- Alert on 404s — they mean the monitoring check was deleted
- Keep ping frequency within the service's rate limits
When it happens
Trigger: Calling Ping() when the heartbeat service returns 404 (check deleted/expired), 401/403 (wrong ping key), 429 (rate limited), or 5xx (service error).
Common situations: Healthchecks.io check was deleted or auto-provisioned with a different URL; ping key rotated; self-hosted heartbeat behind an auth proxy returning 401; service returning 5xx during an outage.
Related errors
- create request: %w
- http request: %w
- heartbeat URL must be a valid HTTP or HTTPS URL
- failed to read response: %w
- info failed: %s
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/75883f7507c4d87a.
Report an issue: GitHub.