crowdsecurity/crowdsec · error

loading plugin: %w

Error message

loading plugin: %w

What it means

Init wraps any failure from loadPlugins (discover, spawn via gRPC, and register each notification plugin binary) with the message "loading plugin: %w". It is the top-level wrapper: the underlying cause (bad binary, failed startup, config error) is chained. If it fires, the plugin broker could not bring up one or more notification plugins and crowdsec cannot dispatch notifications to them.

Source

Thrown at pkg/csplugin/broker.go:108

type PluginConfigList []PluginConfig

func (pb *PluginBroker) Init(ctx context.Context, pluginCfg *csconfig.PluginCfg, profileConfigs []*csconfig.ProfileCfg, configPaths *csconfig.ConfigurationPaths) error {
	pb.PluginChannel = make(chan models.ProfileAlert)
	pb.notificationPluginByName = make(map[string]protobufs.NotifierServer)
	pb.pluginMap = make(map[string]plugin.Plugin)
	pb.pluginConfigByName = make(map[string]PluginConfig)
	pb.alertsByPluginName = make(map[string][]*models.Alert)
	pb.profileConfigs = profileConfigs
	pb.pluginProcConfig = pluginCfg
	pb.pluginsTypesToDispatch = make(map[string]struct{})

	if err := pb.loadConfig(configPaths.NotificationDir); err != nil {
		return fmt.Errorf("loading config: %w", err)
	}

	if err := pb.loadPlugins(ctx, configPaths.PluginDir); err != nil {
		return fmt.Errorf("loading plugin: %w", err)
	}

	pb.watcher = PluginWatcher{}
	pb.watcher.Init(pb.pluginConfigByName, pb.alertsByPluginName)

	return nil
}

func (pb *PluginBroker) ensureBackoff() backoffFactory {
	if pb.newBackoff == nil {
		pb.newBackoff = defaultBackoffFactory
	}
	return pb.newBackoff
}

func (pb *PluginBroker) Kill() {
	for _, kill := range pb.pluginKillMethods {
		kill()

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the wrapped cause (%w) in the log to see the actual failure (binary not found vs configure error).
  2. Verify plugin binaries exist in the configured plugin_dir and are executable (chmod +x).
  3. Confirm profile.yaml notifications reference plugins that have both a config file and a binary installed.
  4. Rebuild/reinstall the notification plugin from the crowdsec-hub and re-run crowdsec.

Example fix

// before: binary missing in default dir
// after: point config at the right dir
crowdsec:
  plugin_dir: /usr/local/lib/crowdsec/plugins/
  notification_dir: /etc/crowdsec/notifications/
Defensive patterns

Strategy: try-catch

Validate before calling

// before Init
for _, bin := range expectedPlugins {
    if fi, err := os.Stat(filepath.Join(pluginDir, bin)); err != nil || fi.IsDir() {
        return fmt.Errorf("plugin binary %s missing in %s", bin, pluginDir)
    }
}

Try / catch

if err := broker.Init(ctx, cfg); err != nil {
    var loadErr error
    if errors.Unwrap(err) != nil { loadErr = errors.Unwrap(err) }
    log.Fatalf("plugin broker init failed: %v (cause: %v)", err, loadErr)
}

Prevention

When it happens

Trigger: Calling PluginBroker.Init(ctx, configPaths) when loadPlugins fails: a plugin binary is missing from the plugin directory, a binary is not executable, or the plugin fails its gRPC Configure handshake (see error 805).

Common situations: Notification plugin binaries (e.g. notification-email, notification-slack) not installed in /var/lib/crowdsec/plugins or the configured plugin_dir; plugin binary built for the wrong architecture; plugin crashes on startup so Configure fails.

Related errors


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