{"record":{"id":"b1759ea8175c8785","repo":"crowdsecurity/crowdsec","slug":"while-parsing-duration-w","errorCode":null,"errorMessage":"while parsing duration: %w","messagePattern":"while parsing duration: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/alertfilter.go","lineNumber":49,"sourceCode":"\t}\n}\n\nfunc handleScopeFilter(scope string, predicates *[]predicate.Alert) {\n\tif strings.ToLower(scope) == \"ip\" {\n\t\tscope = types.Ip\n\t} else if strings.ToLower(scope) == \"range\" {\n\t\tscope = types.Range\n\t}\n\n\t*predicates = append(*predicates, alert.SourceScopeEQ(scope))\n}\n\nfunc handleTimeFilters(param, value string, predicates *[]predicate.Alert) error {\n\t// crowsdec now always sends duration without days, but we allow them for\n\t// compatibility with other tools\n\tduration, err := cstime.ParseDurationWithDays(value)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"while parsing duration: %w\", err)\n\t}\n\n\ttimePoint := time.Now().UTC().Add(-duration)\n\tif timePoint.IsZero() {\n\t\treturn fmt.Errorf(\"empty time now() - %s\", timePoint.String())\n\t}\n\n\tswitch param {\n\tcase \"since\":\n\t\t*predicates = append(*predicates, alert.StartedAtGTE(timePoint))\n\tcase \"created_before\":\n\t\t*predicates = append(*predicates, alert.CreatedAtLTE(timePoint))\n\tcase \"until\":\n\t\t*predicates = append(*predicates, alert.StartedAtLTE(timePoint))\n\t}\n\n\treturn nil\n}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/alertfilter.go#L31-L67","documentation":"Returned by handleTimeFilters when cstime.ParseDurationWithDays cannot parse the 'since' / 'created_*' filter value into a duration. The LAPI alert filters accept Go-style durations (optionally with days) and this error wraps the parse failure.","triggerScenarios":"A LAPI/ cscli alerts query carries a time filter param (e.g. since=...) whose value is not a valid duration string, such as since=abc or since=3 (no unit).","commonSituations":"Typoed duration in API queries or scripts hitting the Local API, forgetting 'h'/'d' suffix (e.g. since=24 instead of 24h), or integrations sending epoch timestamps instead of durations.","solutions":["Correct the duration value to a supported format: '2h', '30m', '7d' (days allowed by cstime), e.g. ?since=24h.","Use RFC3339-free duration strings; do not send timestamps in this parameter.","If a client library builds the query, escape/validate the duration before sending.","Check cstime.ParseDurationWithDays docs for accepted syntax (with/without days)."],"exampleFix":"// before\nGET /v1/alerts?since=24\n// after\nGET /v1/alerts?since=24h","handlingStrategy":"validation","validationCode":"re := regexp.MustCompile(`^\\d+(ns|us|µs|ms|s|m|h|d)$`)\nif !re.MatchString(value) {\n    return fmt.Errorf(\"duration %q invalid; use e.g. 24h or 7d\", value)\n}","typeGuard":null,"tryCatchPattern":"preds, err := alertPredicatesFromFilter(filter)\nvar inv *InvalidFilterError\nif err != nil {\n    if errors.As(err, &inv) { /* return 400 to client */ }\n    return err\n}","preventionTips":["Always include a unit suffix in duration params (24h, 7d)","Validate query params client-side before calling LAPI","Use cscli instead of raw curl where possible","Document accepted duration syntax for your API consumers"],"tags":["go","lapi","duration"],"backgroundTag":"invalid-duration-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}