{"record":{"id":"75883f7507c4d87a","repo":"benbjohnson/litestream","slug":"unexpected-status-code-d","errorCode":null,"errorMessage":"unexpected status code: %d","messagePattern":"unexpected status code: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"heartbeat.go","lineNumber":62,"sourceCode":"\nfunc (c *HeartbeatClient) Ping(ctx context.Context) error {\n\tif c.URL == \"\" {\n\t\treturn nil\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, c.URL, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create request: %w\", err)\n\t}\n\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"http request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\treturn fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode)\n\t}\n\n\treturn nil\n}\n\nfunc (c *HeartbeatClient) ShouldPing() bool {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\treturn time.Since(c.lastPingAt) >= c.Interval\n}\n\nfunc (c *HeartbeatClient) LastPingAt() time.Time {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\treturn c.lastPingAt\n}\n\nfunc (c *HeartbeatClient) RecordPing() {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/heartbeat.go#L44-L80","documentation":"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.","triggerScenarios":"Calling Ping() when the heartbeat service returns 404 (check deleted/expired), 401/403 (wrong ping key), 429 (rate limited), or 5xx (service error).","commonSituations":"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.","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"],"exampleFix":"# before — stale check URL\nheartbeat:\n  url: https://hc-ping.com/old-expired-uuid\n\n# after — recreated check\nheartbeat:\n  url: https://hc-ping.com/new-active-uuid","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := hb.Ping(ctx); err != nil {\n    var statusErr interface{ StatusCode() int }\n    // compare reported status code in the error text and alert on 4xx\n    logger.Warn(\"heartbeat non-2xx\", \"error\", err)\n}","preventionTips":["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"],"tags":["http","heartbeat","status-code","monitoring"],"backgroundTag":"http-non-2xx-response","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"}