{"record":{"id":"f1cf9ed7283c1ed7","repo":"crowdsecurity/crowdsec","slug":"start-at-field-time-s-w-w","errorCode":null,"errorMessage":"start_at field time '%s': %w: %w","messagePattern":"start_at field time '(.+?)': %w: %w","errorType":"exception","errorClass":"ParseTimeFail","httpStatus":null,"severity":"error","filePath":"pkg/database/alerts.go","lineNumber":204,"sourceCode":"\treturn \"\", nil\n}\n\n// UpdateCommunityBlocklist is called to update either the community blocklist (or other lists the user subscribed to)\n// it takes care of creating the new alert with the associated decisions, and it will as well deleted the \"older\" overlapping decisions:\n// 1st pull, you get decisions [1,2,3]. it inserts [1,2,3]\n// 2nd pull, you get decisions [1,2,3,4]. it inserts [1,2,3,4] and will try to delete [1,2,3,4] with a different alert ID and same origin\nfunc (c *Client) UpdateCommunityBlocklist(ctx context.Context, alertItem *models.Alert) (int, int, int, error) {\n\tif alertItem == nil {\n\t\treturn 0, 0, 0, errors.New(\"nil alert\")\n\t}\n\n\tif alertItem.StartAt == nil {\n\t\treturn 0, 0, 0, errors.New(\"nil start_at\")\n\t}\n\n\tstartAtTime, err := time.Parse(time.RFC3339, *alertItem.StartAt)\n\tif err != nil {\n\t\treturn 0, 0, 0, fmt.Errorf(\"start_at field time '%s': %w: %w\", *alertItem.StartAt, err, ParseTimeFail)\n\t}\n\n\tif alertItem.StopAt == nil {\n\t\treturn 0, 0, 0, errors.New(\"nil stop_at\")\n\t}\n\n\tstopAtTime, err := time.Parse(time.RFC3339, *alertItem.StopAt)\n\tif err != nil {\n\t\treturn 0, 0, 0, fmt.Errorf(\"stop_at field time '%s': %w: %w\", *alertItem.StopAt, err, ParseTimeFail)\n\t}\n\n\tts, err := time.Parse(time.RFC3339, *alertItem.StopAt)\n\tif err != nil {\n\t\tc.Log.Errorf(\"While parsing StartAt of item %s : %s\", *alertItem.StopAt, err)\n\n\t\tts = time.Now().UTC()\n\t}\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/alerts.go#L186-L222","documentation":"UpdateCommunityBlocklist requires alertItem.StartAt to be a RFC3339-formatted timestamp string; when time.Parse(time.RFC3339, *alertItem.StartAt) fails, the raw value and the parse error are wrapped with the sentinel ParseTimeFail so callers can test for it. It indicates the alert payload (normally received from CAPI) carries a malformed start_at timestamp.","triggerScenarios":"Calling UpdateCommunityBlocklist (directly or via SaveAlerts when processing pulled CAPI/community-blocklist alerts) with an alert whose StartAt is empty, non-RFC3339 (e.g. '2024-01-02 15:04:05' without timezone, unix epoch, or locale format).","commonSituations":"A custom or third-party blocklist source pushes alerts with non-RFC3339 dates; a data-conversion/migration script builds models.Alert by hand; an older/newer CAPI payload format differs.","solutions":["Log the offending StartAt value and fix the producer to emit RFC3339 (e.g. time.Now().UTC().Format(time.RFC3339))","Pre-parse/normalize timestamps before calling SaveAlerts/UpdateCommunityBlocklist","Check errors.Is(err, database.ParseTimeFail) in the caller to distinguish parse failures from DB errors and skip the bad alert instead of aborting the whole pull"],"exampleFix":"// before\nalert.StartAt = ptr(\"2026-09-06 12:00:00\")\n// after\nalert.StartAt = ptr(time.Now().UTC().Format(time.RFC3339))","handlingStrategy":"validation","validationCode":"if alert.StartAt == nil {\n    return errors.New(\"alert missing start_at\")\n}\nif _, err := time.Parse(time.RFC3339, *alert.StartAt); err != nil {\n    return fmt.Errorf(\"invalid start_at %q: %w\", *alert.StartAt, err)\n}","typeGuard":"func validRFC3339(s *string) bool {\n    if s == nil { return false }\n    _, err := time.Parse(time.RFC3339, *s)\n    return err == nil\n}","tryCatchPattern":"if _, _, _, err := db.UpdateCommunityBlocklist(ctx, alert); err != nil {\n    if errors.Is(err, database.ParseTimeFail) {\n        log.Warnf(\"skipping alert with bad start_at: %v\", err)\n        return nil\n    }\n    return err\n}","preventionTips":["Always produce timestamps with t.UTC().Format(time.RFC3339)","Never hand-format timestamps with spaces or local zones in alert payloads","Test list-source payloads for RFC3339 conformance before ingest"],"tags":["timestamp","rfc3339","capi"],"backgroundTag":"invalid-date-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"}