thanos-io/thanos · error
create request
Error message
create %s request
What it means
In promclient's req2xx helper, http.NewRequest failed while building the outgoing API request. The error wraps the underlying reason (bad method, unparseable URL, invalid body) with the message "create <method> request". No network traffic has happened yet.
Solutions
- Validate the base URL with url.Parse and require a scheme before calling the client
- URL-encode query values (url.Values.Encode) instead of string concatenation
- Use only valid HTTP method constants
- Log/inspect the wrapped error to see which URL component failed
Example fix
// before
u, _ := url.Parse(baseURL + "/api/v1/query?query=" + query)
// after
u, err := url.Parse(baseURL)
if err != nil { return err }
u.Path = "/api/v1/query"
u.RawQuery = url.Values{"query": []string{query}}.Encode() Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(promURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid prometheus URL %q", promURL)
} Type guard
func isValidURL(raw string) bool {
u, err := url.Parse(raw)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
} Try / catch
flags, _, err := client.BuildVersion(ctx, promURL)
if err != nil && strings.Contains(err.Error(), "create request") {
// malformed URL/method: fix config, do not retry
return err
} Prevention
- Build URLs with url.Values and url.Parse, never string concatenation
- Require scheme+host in URL config flags and validate at startup
- Only use standard HTTP method constants
When it happens
Trigger: Calling any client wrapper (ExternalLabels, QueryInstant, QueryRange, AlertmanagerAlerts, BuildVersion) with a URL that fails url.Parse or an invalid HTTP method, e.g. a malformed promURL containing spaces or bad characters.
Common situations: Misconfigured --prometheus.url flag with typos or unencoded characters; programmatically built URLs missing scheme ("localhost:9090" without http://); empty base 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
- creating request to downstream URL
- expected 2xx response, got
- create request
- unable to create request
- setup downstream roundtripper
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/de804b0e4fdc589e.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/promclient/promclient.go:120
httpClient,
logger,
userAgent,
)
}
// req2xx sends a request to the given url.URL. If method is http.MethodPost then
// the raw query is encoded in the body and the appropriate Content-Type is set.
func (c *Client) req2xx(ctx context.Context, u *url.URL, method string, headers http.Header) (_ []byte, _ int, err error) {
var b io.Reader
if method == http.MethodPost {
rq := u.RawQuery
b = strings.NewReader(rq)
u.RawQuery = ""
}
req, err := http.NewRequest(method, u.String(), b)
if err != nil {
return nil, 0, errors.Wrapf(err, "create %s request", method)
}
if headers != nil {
req.Header = headers
}
if c.userAgent != "" {
req.Header.Set("User-Agent", c.userAgent)
}
if method == http.MethodPost {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
resp, err := c.Do(req.WithContext(ctx))
if err != nil {
return nil, 0, errors.Wrapf(err, "perform %s request against %s", method, u.String())
}
defer runutil.ExhaustCloseWithErrCapture(&err, resp.Body, "%s: close body", req.URL.String())
View on GitHub (pinned to 35b8b99117)