{"record":{"id":"ca67ae361ec06e3d","repo":"crowdsecurity/crowdsec","slug":"query-is-mandatory-at-least-start-date-and-end-da","errorCode":null,"errorMessage":"query is mandatory (at least start_date and end_date or backlog)","messagePattern":"query is mandatory \\(at least start_date and end_date or backlog\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/cloudwatch/config.go","lineNumber":207,"sourceCode":"\n\t\ttargetStream = *s.Config.StreamRegexp\n\t} else if s.Config.StreamName != nil {\n\t\ttargetStream = *s.Config.StreamName\n\t}\n\n\ts.logger.Infof(\"Adding cloudwatch group '%s' (stream:%s) to datasources\", s.Config.GroupName, targetStream)\n\n\treturn nil\n}\n\nfunc (s *Source) ConfigureByDSN(ctx context.Context, dsn string, labels map[string]string, logger *log.Entry, uuid string) error {\n\ts.logger = logger\n\n\tdsn = strings.TrimPrefix(dsn, s.GetName()+\"://\")\n\n\targs := strings.Split(dsn, \"?\")\n\tif len(args) != 2 {\n\t\treturn errors.New(\"query is mandatory (at least start_date and end_date or backlog)\")\n\t}\n\n\tfrags := strings.Split(args[0], \":\")\n\tif len(frags) != 2 {\n\t\treturn errors.New(\"cloudwatch path must contain group and stream : /my/group/name:stream/name\")\n\t}\n\n\ts.Config.GroupName = frags[0]\n\ts.Config.StreamName = &frags[1]\n\ts.Config.Labels = labels\n\ts.Config.UniqueId = uuid\n\n\tu, err := url.ParseQuery(args[1])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"while parsing %s: %w\", dsn, err)\n\t}\n\n\tfor k, v := range u {","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/cloudwatch/config.go#L189-L225","documentation":"ConfigureByDSN parses a cloudwatch DSN of the form cloudwatch:///group:stream?query. The DSN must contain exactly one '?' separating path from query parameters (which must include date ranges or backlog). Any DSN that doesn't split into exactly 2 parts on '?' is rejected.","triggerScenarios":"ConfigureByDSN called with a DSN containing no '?' or more than one '?', e.g. cloudwatch:///my/group:stream (no params) or a URL-encoded '?' inside a parameter value.","commonSituations":"Building DSNs programmatically without query parameters; forgetting to URL-encode values so an extra '?' appears; old/example DSN strings copied without the query part.","solutions":["Append a query string with start_date & end_date or backlog, e.g. cloudwatch:///my/group:stream?backlog=1h","URL-encode parameter values so no stray '?' breaks the split","Use the two-part form path?query exactly once"],"exampleFix":"// before\ncloudwatch:///my/log/group:my-stream\n// after\ncloudwatch:///my/log/group:my-stream?backlog=1h","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(dsn)\nif !strings.Contains(u.RawQuery, \"backlog=\") && !strings.Contains(u.RawQuery, \"start_date=\") {\n    return errors.New(\"cloudwatch DSN needs ?backlog= or start_date/end_date\")\n}","typeGuard":"func validCWDSN(dsn string) bool { parts := strings.Split(strings.TrimPrefix(dsn, \"cloudwatch://\"), \"?\"); return len(parts) == 2 }","tryCatchPattern":"if err := src.ConfigureByDSN(dsn, logger, labels, uuid); err != nil {\n    if strings.Contains(err.Error(), \"query is mandatory\") { /* append ?backlog= or date range */ }\n    return err\n}","preventionTips":["Always include a query part (?backlog= or start_date/end_date) in the DSN","URL-encode parameter values","Store DSNs as constants/templates instead of hand-editing"],"tags":["cloudwatch","aws","dsn","url"],"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"}