crowdsecurity/crowdsec · error
element at index %d is not a time.Time
Error message
element at index %d is not a time.Time
What it means
AverageInterval computes the mean duration between consecutive timestamps in a slice. When the expression runtime passes a []interface{}, each element is asserted to time.Time; if any element is a different type (string, float, nil), the function stops and returns this error with the offending index, because it cannot do time arithmetic on non-time values.
Source
Thrown at pkg/exprhelpers/helpers.go:677
// func AverageInterval(times []time.Time) time.Duration
func AverageInterval(params ...any) (any, error) {
if len(params) != 1 {
return 0, errors.New("AverageInterval expects exactly one parameter: a slice of times")
}
var times []time.Time
// Handle both []time.Time and []interface{} (from expr map function)
switch v := params[0].(type) {
case []time.Time:
times = v
case []interface{}:
times = make([]time.Time, len(v))
for i, item := range v {
t, ok := item.(time.Time)
if !ok {
return 0, fmt.Errorf("element at index %d is not a time.Time", i)
}
times[i] = t
}
default:
return 0, errors.New("AverageInterval expects a slice of times")
}
if len(times) < 2 {
return 0, errors.New("need at least two times to calculate an average interval")
}
// Sort times in ascending order
sort.Slice(times, func(i, j int) bool {
return times[i].Before(times[j])
})
var total time.Duration
for i := 1; i < len(times); i++ {View on GitHub (pinned to 909b515798)
Solutions
- Parse each element to time.Time before averaging: ensure the field is populated via a ParseDate node so elements are time.Time
- Check the element at the reported index in your data — it will show the unexpected type
- If elements are strings, convert them first (e.g. a helper that parses each entry) rather than passing raw strings
- Guard the expression so AverageInterval is only evaluated when the field was produced by a date parser
Example fix
// before
AverageInterval(event.GetField('leaks')) // elements are strings
// after
// ensure a parse node precedes it, e.g. list populated via ParseDate so elements are time.Time Defensive patterns
Strategy: type-guard
Validate before calling
// expr: all elements must be times // len(times) > 0 && ...
Type guard
func allTimes(v []interface{}) bool {
for _, item := range v {
if _, ok := item.(time.Time); !ok {
return false
}
}
return len(v) > 0
} Prevention
- Populate slice fields via ParseDate so elements are time.Time
- Never store raw string timestamps in fields later used by time helpers
- Test expressions against events with missing/nil entries
When it happens
Trigger: Calling AverageInterval() in an expr expression on an event field that is a []interface{} containing non-time.Time elements, e.g. event.GetField('leaks') built from parsed logs where entries were stored as strings or numbers instead of time.Time.
Common situations: Parser nodes storing raw string dates into a list field instead of parsed timestamps; expression built before a date parser node (ParseDate) was applied; nil entries in the slice from missing optional fields.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- AverageInterval expects a slice of times
- groupby wrong type
- unexpected type %t (%v) while running '%s'
- invalid type for ip : %T
- invalid type for url: %T
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/8c17f8b909d70cd1.
Report an issue: GitHub.