{"record":{"id":"52f788a748d4b4f3","repo":"crowdsecurity/crowdsec","slug":"loading-config-w","errorCode":null,"errorMessage":"loading config: %w","messagePattern":"loading config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csplugin/broker.go","lineNumber":104,"sourceCode":"\n\t*pc = PluginConfig(aux)\n\treturn nil\n}\n\ntype PluginConfigList []PluginConfig\n\nfunc (pb *PluginBroker) Init(ctx context.Context, pluginCfg *csconfig.PluginCfg, profileConfigs []*csconfig.ProfileCfg, configPaths *csconfig.ConfigurationPaths) error {\n\tpb.PluginChannel = make(chan models.ProfileAlert)\n\tpb.notificationPluginByName = make(map[string]protobufs.NotifierServer)\n\tpb.pluginMap = make(map[string]plugin.Plugin)\n\tpb.pluginConfigByName = make(map[string]PluginConfig)\n\tpb.alertsByPluginName = make(map[string][]*models.Alert)\n\tpb.profileConfigs = profileConfigs\n\tpb.pluginProcConfig = pluginCfg\n\tpb.pluginsTypesToDispatch = make(map[string]struct{})\n\n\tif err := pb.loadConfig(configPaths.NotificationDir); err != nil {\n\t\treturn fmt.Errorf(\"loading config: %w\", err)\n\t}\n\n\tif err := pb.loadPlugins(ctx, configPaths.PluginDir); err != nil {\n\t\treturn fmt.Errorf(\"loading plugin: %w\", err)\n\t}\n\n\tpb.watcher = PluginWatcher{}\n\tpb.watcher.Init(pb.pluginConfigByName, pb.alertsByPluginName)\n\n\treturn nil\n}\n\nfunc (pb *PluginBroker) ensureBackoff() backoffFactory {\n\tif pb.newBackoff == nil {\n\t\tpb.newBackoff = defaultBackoffFactory\n\t}\n\treturn pb.newBackoff\n}","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csplugin/broker.go#L86-L122","documentation":"PluginBroker.Init sets up the notification plugin system and first loads plugin configurations from the notifications yaml directory (loadConfig). Any error reading/parsing that directory (missing dir, unreadable files, invalid yaml configs) is wrapped as 'loading config'. Without it, no notification plugins can be dispatched and LAPI startup aborts.","triggerScenarios":"config_paths.notification_dir (default /etc/crowdsec/notifications/) is missing, unreadable, or contains yaml files whose plugin configs fail to parse (wrong structure for http/email/slack/splunk plugins).","commonSituations":"Fresh installs where the notifications dir wasn't created; hand-written notification yamls with malformed fields; packages upgraded such that old plugin config keys no longer match; permission issues after manual edits with root-only files.","solutions":["Check the directory exists and is readable: `ls -la /etc/crowdsec/notifications/`; create it if missing.","Run `yamllint /etc/crowdsec/notifications/*.yaml` and fix the syntax/schema error in the offending file (the wrapped error names it).","Validate the plugin config structure against the stock example for that plugin type (email.yaml, http.yaml, slack.yaml).","Fix file permissions so the crowdsec user can read the notification configs: `chown -R crowdsec:crowdsec /etc/crowdsec/notifications`.","Temporarily move suspect yaml files out of the directory and restart to isolate the broken one."],"exampleFix":"// before (notifications/email.yaml, missing required 'format')\ntype: email\nname: email_default\n// after\ntype: email\nname: email_default\nformat: >-\n  Crowdsec alert\n...","handlingStrategy":"validation","validationCode":"dir := configPaths.NotificationDir\ninfo, err := os.Stat(dir)\nif err != nil {\n    return fmt.Errorf(\"notification dir %s missing: %w\", dir, err)\n}\nif !info.IsDir() { return fmt.Errorf(\"%s is not a directory\", dir) }\nfiles, _ := os.ReadDir(dir)\nfor _, f := range files {\n    if strings.HasSuffix(f.Name(), \".yaml\") || strings.HasSuffix(f.Name(), \".yml\") {\n        if _, err := os.ReadFile(filepath.Join(dir, f.Name())); err != nil {\n            return fmt.Errorf(\"unreadable notification config %s: %w\", f.Name(), err)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := broker.Init(ctx, configPaths, pluginCfg, profileConfigs); err != nil {\n    if strings.Contains(err.Error(), \"loading config\") {\n        // fix or remove the broken yaml in notification_dir, then retry\n    }\n    return err\n}","preventionTips":["Ensure /etc/crowdsec/notifications exists with crowdsec-readable permissions after installs.","Validate every notification yaml (yamllint + schema check against the plugin's example).","Re-validate notification configs after crowdsec upgrades as plugin config schemas evolve.","Keep plugin configs owned by crowdsec:crowdsec with mode 640/644."],"tags":["plugins","notifications","config"],"backgroundTag":"config-file-not-found","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}