{"record":{"id":"e5b4768960fdd4b2","repo":"benbjohnson/litestream","slug":"create-request-w","errorCode":null,"errorMessage":"create request: %w","messagePattern":"create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"heartbeat.go","lineNumber":52,"sourceCode":"\n\treturn &HeartbeatClient{\n\t\tURL:      url,\n\t\tInterval: interval,\n\t\tTimeout:  timeout,\n\t\thttpClient: &http.Client{\n\t\t\tTimeout: timeout,\n\t\t},\n\t}\n}\n\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()","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/heartbeat.go#L34-L70","documentation":"HeartbeatClient.Ping() failed to construct the HTTP GET request to the configured heartbeat URL via http.NewRequestWithContext. This is rare in Go and almost always means the URL failed to parse (invalid scheme, control characters, malformed host). Ping returns early if URL is empty, so this only fires with a set but invalid URL.","triggerScenarios":"Calling Ping() with c.URL set to a string that url.Parse rejects — e.g. missing scheme, embedded spaces or control characters, malformed percent-encoding, or a nil-request-inducing invalid method/URL combination.","commonSituations":"Typo in heartbeat URL in litestream.yml (missing http://); config expansion producing a URL with a trailing newline or spaces; shell interpolation injecting unexpected characters into the URL.","solutions":["Validate the heartbeat URL is a well-formed absolute URL with http:// or https:// scheme","Check the config file for stray whitespace/newlines in the url value","Test the URL with `curl -v '<url>'` to confirm it parses and is reachable","If the URL is intentionally unset, leave it empty (Ping is a no-op then) rather than a malformed string"],"exampleFix":"# before\nheartbeat:\n  url: healthchecks.io/ping/abc123   # missing scheme\n\n# after\nheartbeat:\n  url: https://healthchecks.io/ping/abc123","handlingStrategy":"validation","validationCode":"if hb.URL != \"\" {\n    if u, err := url.Parse(hb.URL); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n        return fmt.Errorf(\"invalid heartbeat url: %q\", hb.URL)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := hb.Ping(ctx); err != nil {\n    if strings.Contains(err.Error(), \"create request\") {\n        // malformed URL — fix config\n    }\n    return err\n}","preventionTips":["Validate the heartbeat URL at config-load time with url.Parse","Always include the scheme (https://) in configured URLs","Test config URLs with curl before deploying"],"tags":["http","url","heartbeat","configuration"],"backgroundTag":"invalid-url-format","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"}