crowdsecurity/crowdsec · error

leaky.BucketConfig is nil

Error message

leaky.BucketConfig is nil

What it means

NewAlert builds an overflow alert from a leaky bucket; it requires leaky.Factory (the BucketConfig) to be set because the alert carries bucket metadata. A nil Factory means the bucket holder was mis-initialized, so alert construction is refused.

Source

Thrown at pkg/leakybucket/overflows.go:341

	scenarioHash := leaky.Factory.scenarioHash
	scenarioVersion := leaky.Factory.Spec.ScenarioVersion
	simulated := leaky.Factory.Simulated
	apiAlert := models.Alert{
		Scenario:        &scenario,
		ScenarioHash:    &scenarioHash,
		ScenarioVersion: &scenarioVersion,
		Capacity:        &capacity,
		EventsCount:     &EventsCount,
		Leakspeed:       &leakSpeed,
		Message:         new(string),
		StartAt:         &startAt,
		StopAt:          &stopAt,
		Simulated:       &simulated,
		Kind:            types.CrowdsecAlertKind.String(),
	}

	if leaky.Factory == nil {
		return runtimeAlert, errors.New("leaky.BucketConfig is nil")
	}

	// give information about the bucket
	runtimeAlert.Mapkey = leaky.Mapkey

	// Get the sources from Leaky/Queue
	sources, source_scope, err := alertFormatSource(leaky, queue)
	if err != nil {
		return runtimeAlert, fmt.Errorf("unable to collect sources from bucket: %w", err)
	}

	runtimeAlert.Sources = sources
	// Include source info in format string
	sourceStr := "UNKNOWN"
	if len(sources) > 1 {
		sourceStr = fmt.Sprintf("%d sources", len(sources))
	} else if len(sources) == 1 {
		for k := range sources {

View on GitHub (pinned to 909b515798)

Solutions

  1. Ensure buckets are created through the normal LoadOrStoreBucketFromHolder/Build pipeline so Factory is populated
  2. In custom code, assign the BucketFactory to leaky.Factory before calling NewAlert
  3. Check initialization order in tests (TestAlertDoesNotShareStringsWithFactory constructs holders manually)

Example fix

// before
leaky := &leakybucket.Leaky{}
alert, err := leaky.NewAlert(evt)
// after
leaky := &leakybucket.Leaky{Factory: bucketFactory}
alert, err := leaky.NewAlert(evt)
Defensive patterns

Strategy: type-guard

Validate before calling

if leaky.Factory == nil {
    return errors.New("bucket holder not initialized: Factory missing before NewAlert")
}

Type guard

func factoryReady(l *leakybucket.Leaky) bool { return l != nil && l.Factory != nil }

Try / catch

if alert, err := leaky.NewAlert(evt); err != nil {
    if err.Error() == "leaky.BucketConfig is nil" {
        return fmt.Errorf("bucket %s mis-initialized (no factory)", leaky.Mapkey)
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewAlert on a Leaky whose Factory field was never assigned (bucket holder created without a factory), before extracting sources.

Common situations: Custom Go code or tests constructing a Leaky struct directly without Build/BucketFactory wiring, or a regression in bucket initialization order.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/7e3dd1ca087d21c9. Report an issue: GitHub.