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

  1. Check the reported status code: 404 => recreate the check or update the URL in config; 401/403 => fix the ping key/credentials
  2. Verify the heartbeat check still exists in the monitoring service dashboard
  3. For 429, reduce ping frequency or check rate limits
  4. For 5xx, retry later — the heartbeat service is having issues
  5. 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

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


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