crowdsecurity/crowdsec · error
failed to create request: %w
Error message
failed to create request: %w
What it means
GetPermissions queries the PAPI /permissions endpoint to check the console's subscription plan and permission categories. This error is returned when http.NewRequestWithContext fails to build the GET request — essentially only from an invalid URL composition (p.URL + PAPIVersion + PAPIPermissionsURL) such as a control character or unparseable scheme/host. The permission check aborts and no HTTP call is attempted.
Source
Thrown at pkg/apiserver/papi.go:169
metrics.PapiOrdersReceived.WithLabelValues(message.Header.OperationType, message.Header.OperationCmd).Inc()
logger.Debugf("Calling operation '%s'", message.Header.OperationType)
err := operationFunc(ctx, message, p, sync)
if err != nil {
return fmt.Errorf("'%s %s failed: %w", message.Header.OperationType, message.Header.OperationCmd, err)
}
return nil
}
func (p *Papi) GetPermissions(ctx context.Context) (PapiPermCheckSuccess, error) {
httpClient := p.apiClient.GetClient()
papiCheckURL := fmt.Sprintf("%s%s%s", p.URL, PAPIVersion, PAPIPermissionsURL)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, papiCheckURL, http.NoBody)
if err != nil {
return PapiPermCheckSuccess{}, fmt.Errorf("failed to create request: %w", err)
}
resp, err := httpClient.Do(req)
if err != nil {
return PapiPermCheckSuccess{}, fmt.Errorf("failed to get response: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
errResp := PapiPermCheckError{}
err = json.NewDecoder(resp.Body).Decode(&errResp)
if err != nil {
return PapiPermCheckSuccess{}, fmt.Errorf("failed to decode response: %w", err)
}
return PapiPermCheckSuccess{}, fmt.Errorf("unable to query PAPI : %s (%d)", errResp.Error, resp.StatusCode)View on GitHub (pinned to 909b515798)
Solutions
- Inspect api.client.papi_url in config.yaml for typos, missing https:// scheme, stray spaces or quotes.
- Validate config with `crowdsec -t` after fixing.
- Test the composed URL manually: <papi_url>v1/permissions should be syntactically valid in a browser/curl.
- If unset, restore the default papi_url (https://api.crowdsec.net/).
Example fix
// before (config.yaml)
api:
client:
papi_url: "https://api.crowdsec.net/ "
// after
api:
client:
papi_url: https://api.crowdsec.net/ Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(papiBaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid papi url %q", papiBaseURL)
} Try / catch
perms, err := papi.GetPermissions(ctx)
if err != nil {
if strings.Contains(err.Error(), "failed to create request") {
// configuration-level URL problem: do not retry, fix config
return fmt.Errorf("check api.client.papi_url: %w", err)
}
} Prevention
- Validate papi_url with a URL parser at config load time.
- Trim whitespace/quotes from URL values loaded from env or templates.
- Run config tests (`crowdsec -t`) in CI for deployed crowdsec configurations.
- Keep papi_url at the upstream default unless support directs otherwise.
When it happens
Trigger: Called at PAPI startup / query flows (QueryPAPIInfo) when p.URL (derived from api.client.papi_url) yields a URL that http.NewRequestWithContext rejects — e.g. missing scheme or invalid characters in the configured papi URL.
Common situations: Hand-edited papi_url in config.yaml with a typo or missing scheme; environment-injected URL with trailing whitespace/newline; copy-paste of the base URL with quotes.
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
- path must start with /
- chunk_size must be positive
- invalid HTTP status code
- empty loki host
- errUnauthorized
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/332dfca08137b539.
Report an issue: GitHub.