crowdsecurity/crowdsec · error
unable to parse '%s' as duration: %w
Error message
unable to parse '%s' as duration: %w
What it means
The `backlog` DSN parameter must be a Go duration string parsed with time.ParseDuration (e.g. 2h, 30m). When parsing fails the error is wrapped as `unable to parse '<value>' as duration: <underlying error>`. Configuration stops and the datasource is rejected.
Source
Thrown at pkg/acquisition/modules/cloudwatch/config.go:269
strdate, startDate := parser.GenDateParse(v[0])
s.logger.Debugf("parsed '%s' as '%s'", v[0], strdate)
s.Config.StartTime = &startDate
case "end_date":
if len(v) != 1 {
return errors.New("expected zero or one argument for 'end_date'")
}
// let's reuse our parser helper so that a ton of date formats are supported
strdate, endDate := parser.GenDateParse(v[0])
s.logger.Debugf("parsed '%s' as '%s'", v[0], strdate)
s.Config.EndTime = &endDate
case "backlog":
if len(v) != 1 {
return errors.New("expected zero or one argument for 'backlog'")
}
// let's reuse our parser helper so that a ton of date formats are supported
duration, err := time.ParseDuration(v[0])
if err != nil {
return fmt.Errorf("unable to parse '%s' as duration: %w", v[0], err)
}
s.logger.Debugf("parsed '%s' as '%s'", v[0], duration)
start := time.Now().UTC().Add(-duration)
s.Config.StartTime = &start
end := time.Now().UTC()
s.Config.EndTime = &end
default:
return fmt.Errorf("unexpected argument %s", k)
}
}
s.logger.Tracef("host=%s", s.Config.GroupName)
s.logger.Tracef("stream=%s", *s.Config.StreamName)
s.Config.GetLogEventsPagesLimit = &def_GetLogEventsPagesLimit
if err := s.newClient(ctx); err != nil {
return errView on GitHub (pinned to 909b515798)
Solutions
- Use a Go-standard duration string: 1h30m, 7200s, 24h — note there is no 'd' unit, so 1 day is 24h
- Verify the value has both a number and a unit, e.g. '30m' not '30'
- Compute multi-day backlogs as multiples of 24h, e.g. 3 days = 72h
Example fix
// before cloudwatch://my-group?backlog=2d // after cloudwatch://my-group?backlog=48h
Defensive patterns
Strategy: validation
Validate before calling
v := "48h"
if _, err := time.ParseDuration(v); err != nil {
return fmt.Errorf("backlog must be a Go duration (no 'd' unit): %v", err)
} Try / catch
if err := ds.ConfigureByDSN(ctx, dsn); err != nil {
if strings.Contains(err.Error(), "as duration") { /* normalize backlog value */ }
} Prevention
- Remember Go durations have no days unit — use 24h multiples
- Always include a unit: '30m', not '30'
- Validate duration strings in CI config checks
When it happens
Trigger: ConfigureByDSN called with a DSN like `cloudwatch://group?backlog=2days` or `backlog=3600` — any value without a Go duration unit (h, m, s, etc.) or with an invalid unit.
Common situations: Users write '2d' (Go durations have no day unit), plain integers meaning seconds, or human-friendly strings like 'yesterday'.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unknown level %s: %w
- unexpected argument %s
- failed to load aws config: %w
- group_name is mandatory for CloudwatchSource
- aws_region is not specified, specify it or aws_config_dir
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/4a4408585e5dda27.
Report an issue: GitHub.