crowdsecurity/crowdsec · error
event has multiple source types : %s != %s
Error message
event has multiple source types : %s != %s
What it means
During alert formatting, crowdsec requires every event in the overflow queue to share one source scope type (e.g. all Ip, all Range). When processing queued events, if a second source's Scope differs from the first one recorded, alertFormatSource refuses to build a mixed-type alert with this error. It is an internal consistency check: a single alert cannot represent events scoped to different source types.
Source
Thrown at pkg/leakybucket/overflows.go:287
sources := make(map[string]models.Source)
log.Debugf("Formatting (%s) - scope Info : scope_type:%s / scope_filter:%s", leaky.Factory.Spec.Name, leaky.Factory.Spec.ScopeType.Scope, leaky.Factory.Spec.ScopeType.Filter)
qEvents := queue.GetQueue()
for idx := range qEvents {
srcs, err := SourceFromEvent(qEvents[idx], leaky)
if err != nil {
return nil, "", fmt.Errorf("while extracting scope from bucket %s: %w", leaky.Factory.Spec.Name, err)
}
for key, src := range srcs {
if source_type == types.Undefined {
source_type = *src.Scope
}
if *src.Scope != source_type {
return nil, "",
fmt.Errorf("event has multiple source types : %s != %s", *src.Scope, source_type)
}
sources[key] = src
}
}
return sources, source_type, nil
}
// NewAlert will generate a RuntimeAlert and its APIAlert(s) from a bucket that overflowed
func NewAlert(leaky *Leaky, queue *pipeline.Queue) (pipeline.RuntimeAlert, error) {
var runtimeAlert pipeline.RuntimeAlert
leaky.logger.Tracef("Overflow (start: %s, end: %s)", leaky.First_ts, leaky.Ovflw_ts)
/*
Craft the models.Alert that is going to be duplicated for each source
*/
start_at, err := leaky.First_ts.MarshalText()View on GitHub (pinned to 909b515798)
Solutions
- Check the scenario's scope filter for inputs that can be empty for some events and normalize them (e.g. fall back to evt.Parsed.source_ip)
- Ensure parsers/enrichers populate the fields the scope filter uses for every acquisition source the scenario applies to
- If the scenario is intentionally generic, split it so each log type has its own consistent scope
- Capture a dump of the queued events (leaky.Factory.Spec.Debug=true) to see which event produced the divergent scope
Example fix
// before scope: type: range filter: evt.Enriched.target_ips // after (guarantee a non-empty string) scope: type: range filter: Get(evt.Enriched, 'target_ips', evt.Parsed.target_ip)
Defensive patterns
Strategy: validation
Validate before calling
// Ensure scope filters yield a consistent, non-empty string for all events: // in the expression: Get(field, fallback) — never a bare optional field
Type guard
// Expression-level guard: // val := Get(evt.Enriched, 'target_ips', evt.Parsed.target_ip); val != ''
Try / catch
// If generating alerts yourself:
alert, _, err := alertFormatSource(leaky, queue)
if err != nil && strings.Contains(err.Error(), "multiple source types") {
log.Warnf("mixed-scope overflow in %s; fix the scope filter", leaky.Factory.Spec.Name)
} Prevention
- Normalize scope filter output with a fallback for every event
- Avoid applying one scenario to log types with different source semantics
- Enable leaky.Factory.Spec.Debug to dump scopes of queued events when debugging
- Split generic scenarios per acquisition type
When it happens
Trigger: Bucket overflow where events in the same queue produce srcs whose *src.Scope values differ (e.g. some events yield types.Ip, others types.Range or types.Undefined) — typically when a scope filter returns differently-typed/empty values across events.
Common situations: Custom scope filters that return an empty string or non-string value for some events (which falls back to an undefined scope) while others resolve to an IP/Range; scenarios applied to heterogeneous acquisition sources.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- empty scope information
- leaky.BucketConfig is nil
- while extracting scope from bucket %s: %w
- unable to collect sources from bucket: %w
- invalid generated alert: %w: %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/f0e2151e69415402.
Report an issue: GitHub.