benbjohnson/litestream · warning

http request: %w

Error message

http request: %w

What it means

HeartbeatClient.Ping() sent the GET request to the heartbeat URL but the HTTP transport failed (connection refused, DNS failure, TLS error, timeout). The request never received a response. This is a network-level failure, not an HTTP status problem.

Source

Thrown at heartbeat.go:57

		httpClient: &http.Client{
			Timeout: timeout,
		},
	}
}

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()

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Verify network egress/DNS from the host running litestream (`curl -v <url>`)
  2. Confirm the heartbeat service URL is correct and the service is up
  3. Check for required proxy configuration (HTTP_PROXY/HTTPS_PROXY) in the environment
  4. If TLS errors occur, fix the endpoint certificate or the CA trust store on the host
  5. Note: heartbeat failure doesn't stop replication; it affects liveness monitoring only — but check whether the caller treats this as fatal
Defensive patterns

Strategy: retry

Try / catch

if err := hb.Ping(ctx); err != nil {
    // heartbeat is best-effort: log and retry next interval
    logger.Warn("heartbeat ping failed, will retry", "error", err)
}

Prevention

When it happens

Trigger: Calling Ping() when the heartbeat service is down, DNS doesn't resolve the host, a firewall blocks egress, TLS certificate validation fails, or the request exceeds the httpClient timeout.

Common situations: Healthchecks.io/dead-man's-snitch outage; litestream running in a restricted network (no egress) such as an air-gapped cluster; corporate proxy required but not configured; typo'd hostname; expired TLS cert on a self-hosted heartbeat endpoint.

Related errors


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