{"record":{"id":"643043ebc9ed21ce","repo":"crowdsecurity/crowdsec","slug":"failed-to-build-alert-request-w","errorCode":null,"errorMessage":"failed to build alert request: %w","messagePattern":"failed to build alert request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/alerts.go","lineNumber":777,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"machine '%s': %w\", machineID, err)\n\t\t}\n\t}\n\n\treturn alertIDs, nil\n}\n\nfunc (c *Client) AlertsCountPerScenario(ctx context.Context, filter map[string][]string) (map[string]int, error) {\n\tvar res []struct {\n\t\tScenario string\n\t\tCount    int\n\t}\n\n\tquery := c.Ent.Alert.Query()\n\n\tquery, err := applyAlertFilter(query, filter)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to build alert request: %w\", err)\n\t}\n\n\terr = query.GroupBy(alert.FieldScenario).Aggregate(ent.Count()).Scan(ctx, &res)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to count alerts per scenario: %w\", err)\n\t}\n\n\tcounts := make(map[string]int)\n\n\tfor _, r := range res {\n\t\tcounts[r.Scenario] = r.Count\n\t}\n\n\treturn counts, nil\n}\n\nfunc (c *Client) TotalAlerts(ctx context.Context) (int, error) {\n\treturn c.Ent.Alert.Query().Count(ctx)","sourceCodeStart":759,"sourceCodeEnd":795,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/alerts.go#L759-L795","documentation":"AlertsCountPerScenario fails to build the ent query when applyAlertFilter rejects the provided filter (e.g. an invalid since/until date or malformed filter value). The error reports that the alert-count request could not be constructed.","triggerScenarios":"Calling AlertsCountPerScenario with a filter containing values applyAlertFilter cannot parse (bad time format, invalid field name passed through from a LAPI query string).","commonSituations":"API clients passing malformed `since`/`until` parameters; custom dashboards hitting LAPI /alerts with hand-built query strings; version drift where a filter key was renamed.","solutions":["Fix the filter value that applyAlertFilter rejects (check the wrapped error for the field)","Use RFC3339 for since/until date filters","Check the wrapped error with errors.Is against time parsing sentinels","Validate query parameters on the client before calling the LAPI"],"exampleFix":"// before\nfilter := models.AlertsFilter{\"since\": \"yesterday\"}\ncounts, err := db.AlertsCountPerScenario(ctx, filter)\n// after\nfilter := models.AlertsFilter{\"since\": time.Now().Add(-24 * time.Hour).Format(time.RFC3339)}\ncounts, err := db.AlertsCountPerScenario(ctx, filter)","handlingStrategy":"validation","validationCode":"if since, ok := filter[\"since\"]; ok {\n    if _, err := time.Parse(time.RFC3339, since); err != nil {\n        return fmt.Errorf(\"invalid since: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always send RFC3339 timestamps in since/until filters","Whitelist filter keys on API clients","Test filters against a local LAPI before deploying dashboards"],"tags":["query","filters","validation"],"backgroundTag":"invalid-query-parameter","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"}