crowdsecurity/crowdsec · error
while building request: %w
Error message
while building request: %w
What it means
DecisionDeleteService.Add builds the POST /decisions/delete request via PrepareRequest; if request construction fails (bad URL resolution, trailing-slash BaseURL violation, JSON marshal failure of the DecisionsDeleteRequest, gzip failure, or invalid http.Request), the error is wrapped as 'while building request'. The inner error carries the real cause.
Source
Thrown at pkg/apiclient/decisions_sync_service.go:21
import (
"context"
"fmt"
"net/http"
log "github.com/sirupsen/logrus"
"github.com/crowdsecurity/crowdsec/pkg/models"
)
type DecisionDeleteService service
// DecisionDeleteService purposely reuses AddSignalsRequestItemDecisions model
func (d *DecisionDeleteService) Add(ctx context.Context, deletedDecisions *models.DecisionsDeleteRequest) (interface{}, *Response, error) {
u := fmt.Sprintf("%s/decisions/delete", d.client.URLPrefix)
req, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)
if err != nil {
return nil, nil, fmt.Errorf("while building request: %w", err)
}
var response interface{}
resp, err := d.client.Do(ctx, req, &response)
if err != nil {
return nil, resp, fmt.Errorf("while performing request: %w", err)
}
if resp.Response.StatusCode != http.StatusOK {
log.Warnf("Decisions delete response: http %s", resp.Response.Status)
} else {
log.Debugf("Decisions delete response: http %s", resp.Response.Status)
}
return &response, resp, nil
}
View on GitHub (pinned to 909b515798)
Solutions
- Check the wrapped inner error to identify the concrete cause (URL vs JSON vs gzip)
- Verify the client's BaseURL ends with '/' and is a valid absolute URL
- Ensure DecisionsDeleteRequest contains only JSON-serializable values
- If building the client manually, normalize the URL path before constructing it
Example fix
// before
req, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)
if err != nil {
return nil, nil, fmt.Errorf("while building request: %w", err)
}
// after (caller pre-validation)
if !strings.HasSuffix(d.client.BaseURL.Path, "/") {
return nil, nil, errors.New("client BaseURL must end with a trailing slash")
}
req, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)
if err != nil {
return nil, nil, fmt.Errorf("while building request: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// before calling DecisionDeleteService.Add
if !strings.HasSuffix(client.BaseURL.Path, "/") {
return errors.New("client BaseURL must end with a trailing slash")
}
if _, err := json.Marshal(deletedDecisions); err != nil {
return fmt.Errorf("decisions delete payload not serializable: %w", err)
} Type guard
func canDelete(client *apiclient.ApiClient, req *models.DecisionsDeleteRequest) bool {
return client != nil && strings.HasSuffix(client.BaseURL.Path, "/") && req != nil
} Try / catch
_, _, err := client.DecisionsDelete.Add(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "while building request") {
// client-side construction bug: check BaseURL and payload types
}
return fmt.Errorf("decisions delete failed: %w", err)
} Prevention
- Normalize BaseURL with a trailing slash at client construction
- Only put JSON-serializable values in DecisionsDeleteRequest
- Pre-marshal payloads in tests to catch unserializable fields early
When it happens
Trigger: d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions) returns an error before any network I/O: BaseURL without trailing slash, URL parse failure, or JSON encoding failure of the delete request body.
Common situations: Client constructed with malformed BaseURL (missing trailing slash); passing a body containing unsupported types (e.g. channels, funcs) into DecisionsDeleteRequest; URL prefix misconfigured so c.BaseURL.Parse fails.
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
- authenticate watcher (%s): %w
- while building request: %w
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
- missing lapi client credentials
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b7fddcffbf049f2b.
Report an issue: GitHub.