gastownhall/beads · error
failed to create request: %w
Error message
failed to create request: %w
What it means
http.NewRequestWithContext failed to construct the outbound request. Since method and URL are built internally by the client, this almost always means the resolved URL string is malformed (bad base URL configuration) or the context/method combination is invalid. The error is wrapped and returned without retrying.
Source
Thrown at internal/gitlab/client.go:125
}
reqBody = bytes.NewReader(jsonBody)
}
var lastErr error
for attempt := 0; attempt <= MaxRetries; attempt++ {
// Reset body reader at top of loop so retries after network errors
// don't send empty bodies (the reader may be at EOF).
if body != nil {
jsonBody, err := json.Marshal(body)
if err != nil {
return nil, nil, fmt.Errorf("failed to marshal request body: %w", err)
}
reqBody = bytes.NewReader(jsonBody)
}
req, err := http.NewRequestWithContext(ctx, method, urlStr, reqBody)
if err != nil {
return nil, nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("PRIVATE-TOKEN", c.Token)
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
lastErr = fmt.Errorf("request failed (attempt %d/%d): %w", attempt+1, MaxRetries+1, err)
continue
}
// Limit response body to 50MB to prevent OOM from malformed responses.
const maxResponseSize = 50 * 1024 * 1024
respBody, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize))
_ = resp.Body.Close() // Best effort: HTTP body close; connection may be reused regardless
if err != nil {
lastErr = fmt.Errorf("failed to read response (attempt %d/%d): %w", attempt+1, MaxRetries+1, err)
continueView on GitHub (pinned to 71377f2769)
Solutions
- Verify the configured base URL includes a valid scheme and host (https://gitlab.com/api/v4)
- Trim whitespace from URL config values read from environment or YAML
- Check for special characters in project/group path segments and URL-encode them
- Log the final urlStr by reproducing buildURL with your inputs to spot the malformed piece
Example fix
// before BaseURL: "gitlab.example.com/api/v4" // after BaseURL: "https://gitlab.example.com/api/v4"
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(cfg.BaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid GitLab base URL: %q", cfg.BaseURL)
} Type guard
func validBaseURL(s string) bool {
u, err := url.Parse(s)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to create request") {
return fmt.Errorf("check GitLab base URL config (scheme/host): %w", err)
} Prevention
- Always include the https:// scheme in configured base URLs
- Trim whitespace from URL values read from env/YAML
- URL-encode project/group path segments containing special characters
- Smoke-test the URL with curl before wiring it into config
When it happens
Trigger: A misconfigured base URL (e.g. missing scheme: 'gitlab.example.com/api/v4' instead of 'https://...'), control characters in the URL, or an invalid URL resulting from buildURL parameter concatenation, causing url.Parse inside NewRequestWithContext to fail.
Common situations: Setting GitLabURL or config base URL without the https:// scheme; trailing spaces in an env-provided URL; project/group paths containing characters that break URL parsing; proxy env vars injecting garbage.
Related errors
- failed to create request: %w
- multiple .doltcfg directories detected
- dolt directory is required
- httpapi: a configured role fires this workspace's hooks; thi
- httpapi: the configured provider fires this workspace's hook
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f304c69603776d74.
Report an issue: GitHub.