crowdsecurity/crowdsec · error
groupby wrong type
Error message
groupby wrong type
What it means
After running the groupby expression, the result must be a string to use as the bucket partition key. If the expr returns a non-string (number, bool, array), PourItemToHolders logs a fatal and returns this error instead of building a key.
Source
Thrown at pkg/leakybucket/manager_run.go:255
}
if !condition {
holders[idx].logger.Debugf("Event leaving node : ko (filter mismatch)")
continue
}
}
// groupby determines the partition key for the specific bucket
var groupby string
if holders[idx].RunTimeGroupBy != nil {
tmpGroupBy, err := exprhelpers.Run(holders[idx].RunTimeGroupBy, map[string]any{"evt": &parsed}, holders[idx].logger, holders[idx].Spec.Debug)
if err != nil {
holders[idx].logger.Errorf("failed groupby : %v", err)
return false, errors.New("leaky failed :/")
}
if groupby, ok = tmpGroupBy.(string); !ok {
holders[idx].logger.Fatalf("failed groupby type : %v", err)
return false, errors.New("groupby wrong type")
}
}
buckey := holders[idx].BucketKey(groupby)
// we need to either find the existing bucket, or create a new one (if it's the first event to hit it for this partition key)
bucket, err := LoadOrStoreBucketFromHolder(ctx, buckey, buckets, &holders[idx], parsed.ExpectMode)
if err != nil {
return false, fmt.Errorf("failed to load or store bucket: %w", err)
}
// finally, pour the even into the bucket
if bucket.Factory.orderEvent {
if orderEvent == nil {
orderEvent = make(map[string]*sync.WaitGroup)
}
if orderEvent[buckey] != nil {
orderEvent[buckey].Wait()
} else {View on GitHub (pinned to 909b515798)
Solutions
- Cast the groupby expression to a string, e.g. `groupby: "string(evt.Parsed.status)"` or wrap with fmt
- Group on inherently string fields like evt.Meta.source_ip or evt.Parsed.username
- Restart crowdsec if it hit the Fatalf path, as the process may have exited
Example fix
# before
groupby: "evt.Parsed.status_code"
# after
groupby: "fmt.Sprintf("%v", evt.Parsed.status_code)" Defensive patterns
Strategy: type-guard
Type guard
if s, ok := groupbyResult.(string); ok {
key = s
} else {
return fmt.Errorf("groupby must return string, got %T", groupbyResult)
} Prevention
- Wrap non-string groupby values: fmt.Sprintf("%v", ...)
- Prefer string-typed meta fields for groupby
- Beware numeric Parsed fields — expressions may yield floats
When it happens
Trigger: A scenario's `groupby:` expression evaluates successfully but returns a non-string value, e.g. `groupby: "evt.Parsed.status"` where status is an int.
Common situations: Groupby on numeric or boolean parsed fields, or on lists/maps, when the author intended a string identifier.
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
- missing filter directive
- leaky failed :/
- AverageInterval expects exactly one parameter: a slice of ti
- need at least two times to calculate an average interval
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/60fce9eac94596bb.
Report an issue: GitHub.