crowdsecurity/crowdsec · error

plugin broker: %w

Error message

plugin broker: %w

What it means

InitPlugins wraps errors from pluginBroker.Init, which loads notification plugin binaries and their YAML configs from the plugin directory and builds notifications from profiles. The LAPI continues to serve but notifications will not work — InitPlugins returns the error to the caller.

Source

Thrown at pkg/apiserver/apiserver.go:535

	return false
}

func (s *APIServer) InitPlugins(ctx context.Context, cConfig *csconfig.Config, pluginBroker *csplugin.PluginBroker) error {
	if hasPlugins(s.cfg.Profiles) {
		log.Info("initiating plugin broker")
		// On windows, the plugins are always run as medium-integrity processes, so we don't care about plugin_config
		if cConfig.PluginConfig == nil && runtime.GOOS != "windows" {
			return errors.New("plugins are enabled, but the plugin_config section is missing in the configuration")
		}

		if cConfig.ConfigPaths.PluginDir == "" {
			return errors.New("plugins are enabled, but config_paths.plugin_dir is not defined")
		}

		err := pluginBroker.Init(ctx, cConfig.PluginConfig, s.cfg.Profiles, cConfig.ConfigPaths)
		if err != nil {
			return fmt.Errorf("plugin broker: %w", err)
		}

		log.Info("initiated plugin broker")
		s.AttachPluginBroker(pluginBroker)
	}

	return nil
}

func (s *APIServer) InitController() error {
	err := s.controller.Init()
	if err != nil {
		return fmt.Errorf("controller init: %w", err)
	}

	if s.cfg.TLS == nil {
		return nil
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the wrapped cause for which plugin/config file failed.
  2. Set config_paths.plugin_dir in config.yaml to the directory containing crowdsec-notification-* binaries.
  3. Verify plugin binaries exist and are executable (ls -l on plugin_dir).
  4. Validate the plugin YAML in /etc/crowdsec/notifications/ against the plugin's documented schema.
  5. If notifications aren't wanted, disable them rather than leaving a broken plugin config.

Example fix

// before (config.yaml)
config_paths:
  # plugin_dir not set
// after
config_paths:
  plugin_dir: /usr/lib/crowdsec/plugins/
Defensive patterns

Strategy: validation

Validate before calling

// before enabling notifications
if cfg.PluginConfig != nil || len(cfg.Profiles) > 0 {
    if cConfig.ConfigPaths.PluginDir == "" {
        return fmt.Errorf("notifications configured but config_paths.plugin_dir is empty")
    }
    if ents, _ := os.ReadDir(cConfig.ConfigPaths.PluginDir); len(ents) == 0 {
        return fmt.Errorf("plugin_dir %s is empty", cConfig.ConfigPaths.PluginDir)
    }
}

Try / catch

if err := server.InitPlugins(cConfig, ctx); err != nil {
    if strings.Contains(err.Error(), "plugin broker") {
        log.Errorf("notification plugins failed: %v — LAPI will run without notifications", err)
    }
    return err
}

Prevention

When it happens

Trigger: InitPlugins called with notifications enabled but config_paths.plugin_dir unset (separate errors.New case, same wrapper path), plugin binaries missing/non-executable, or plugin YAML config files malformed.

Common situations: Installed binary-only crowdsec without notification plugins; plugin_dir points to wrong path; a plugin config (e.g. /etc/crowdsec/notifications/http.yaml) has bad yaml or missing required keys.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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