{"record":{"id":"b7fddcffbf049f2b","repo":"crowdsecurity/crowdsec","slug":"while-building-request-w","errorCode":null,"errorMessage":"while building request: %w","messagePattern":"while building request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiclient/decisions_sync_service.go","lineNumber":21,"sourceCode":"import (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/crowdsecurity/crowdsec/pkg/models\"\n)\n\ntype DecisionDeleteService service\n\n// DecisionDeleteService purposely reuses AddSignalsRequestItemDecisions model\nfunc (d *DecisionDeleteService) Add(ctx context.Context, deletedDecisions *models.DecisionsDeleteRequest) (interface{}, *Response, error) {\n\tu := fmt.Sprintf(\"%s/decisions/delete\", d.client.URLPrefix)\n\n\treq, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"while building request: %w\", err)\n\t}\n\n\tvar response interface{}\n\n\tresp, err := d.client.Do(ctx, req, &response)\n\tif err != nil {\n\t\treturn nil, resp, fmt.Errorf(\"while performing request: %w\", err)\n\t}\n\n\tif resp.Response.StatusCode != http.StatusOK {\n\t\tlog.Warnf(\"Decisions delete response: http %s\", resp.Response.Status)\n\t} else {\n\t\tlog.Debugf(\"Decisions delete response: http %s\", resp.Response.Status)\n\t}\n\n\treturn &response, resp, nil\n}\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiclient/decisions_sync_service.go#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreq, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)\nif err != nil {\n    return nil, nil, fmt.Errorf(\"while building request: %w\", err)\n}\n// after (caller pre-validation)\nif !strings.HasSuffix(d.client.BaseURL.Path, \"/\") {\n    return nil, nil, errors.New(\"client BaseURL must end with a trailing slash\")\n}\nreq, err := d.client.PrepareRequest(ctx, http.MethodPost, u, &deletedDecisions)\nif err != nil {\n    return nil, nil, fmt.Errorf(\"while building request: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// before calling DecisionDeleteService.Add\nif !strings.HasSuffix(client.BaseURL.Path, \"/\") {\n    return errors.New(\"client BaseURL must end with a trailing slash\")\n}\nif _, err := json.Marshal(deletedDecisions); err != nil {\n    return fmt.Errorf(\"decisions delete payload not serializable: %w\", err)\n}","typeGuard":"func canDelete(client *apiclient.ApiClient, req *models.DecisionsDeleteRequest) bool {\n    return client != nil && strings.HasSuffix(client.BaseURL.Path, \"/\") && req != nil\n}","tryCatchPattern":"_, _, err := client.DecisionsDelete.Add(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"while building request\") {\n        // client-side construction bug: check BaseURL and payload types\n    }\n    return fmt.Errorf(\"decisions delete failed: %w\", err)\n}","preventionTips":["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"],"tags":["request-building","lapi","api-client"],"backgroundTag":"invalid-url-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}