benbjohnson/litestream · error
create request: %w
Error message
create request: %w
What it means
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.
Source
Thrown at heartbeat.go:52
return &HeartbeatClient{
URL: url,
Interval: interval,
Timeout: timeout,
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()View on GitHub (pinned to 4ed7a308f6)
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
Example fix
# before heartbeat: url: healthchecks.io/ping/abc123 # missing scheme # after heartbeat: url: https://healthchecks.io/ping/abc123
Defensive patterns
Strategy: validation
Validate before calling
if hb.URL != "" {
if u, err := url.Parse(hb.URL); err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid heartbeat url: %q", hb.URL)
}
} Try / catch
if err := hb.Ping(ctx); err != nil {
if strings.Contains(err.Error(), "create request") {
// malformed URL — fix config
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- heartbeat URL must be a valid HTTP or HTTPS URL
- bucket required for abs replica URL
- http request: %w
- unexpected status code: %d
- database config required
AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06).
Data as JSON: /api/errors/e5b4768960fdd4b2.
Report an issue: GitHub.