{"record":{"id":"7b40b9084930810b","repo":"crowdsecurity/crowdsec","slug":"missing-required-field-type","errorCode":null,"errorMessage":"missing required field 'type'","messagePattern":"missing required field 'type'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csplugin/broker.go","lineNumber":80,"sourceCode":"\tMaxRetry       uint          `yaml:\"max_retry,omitempty\"`\n\tTimeOut        time.Duration `yaml:\"timeout,omitempty\"`\n\n\tFormat string `yaml:\"format,omitempty\"` // specific to notification plugins\n\n\tConfig map[string]any `yaml:\",inline\"` // to keep the plugin-specific config\n}\n\n// UnmarshalYAML implements yaml.Unmarshaler.\nfunc (pc *PluginConfig) UnmarshalYAML(unmarshal func(any) error) error {\n\ttype raw PluginConfig\n\taux := raw{}\n\n\tif err := unmarshal(&aux); err != nil {\n\t\treturn err\n\t}\n\n\tif aux.Type == \"\" {\n\t\treturn errors.New(\"missing required field 'type'\")\n\t}\n\n\tif aux.TimeOut == 0 {\n\t\taux.TimeOut = time.Second * 5\n\t}\n\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)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csplugin/broker.go#L62-L98","documentation":"PluginBroker's notification plugin config implements UnmarshalYAML, which requires every plugin entry to declare a 'type' field identifying the plugin kind. An empty type cannot be mapped to a plugin binary/runner, so unmarshaling the YAML fails immediately.","triggerScenarios":"A notification plugin entry in config.yaml (e.g. under the plugin configuration file) that omits 'type:', or spells it 'type :\"\"' / uses a wrong key like 'kind:'.","commonSituations":"Copying a plugin example and deleting the type line; indented YAML under the wrong parent so type isn't decoded into the aux struct; writing a plugin config from a script that emits empty type.","solutions":["Add 'type: <plugin_name>' (matching the plugin binary name, e.g. type: http) to the plugin config entry","Verify the type key is nested at the correct level of the plugin entry, not in a sibling mapping","Check the plugin's documentation for its exact expected type value"],"exampleFix":"// before\nslack:\n  webhook_url: https://hooks.slack.com/...\n\n// after\nslack:\n  type: slack\n  webhook_url: https://hooks.slack.com/...","handlingStrategy":"validation","validationCode":"for name, pc := range pluginConfigs {\n    if pc.Type == \"\" {\n        return fmt.Errorf(\"plugin %q is missing required 'type' field\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := yaml.Unmarshal(raw, &pluginCfg); err != nil {\n    if strings.Contains(err.Error(), \"missing required field 'type'\") {\n        log.Fatalf(\"plugin entry needs a 'type:' key matching the plugin binary\")\n    }\n    return err\n}","preventionTips":["Copy plugin config examples verbatim, including the type line","Validate plugin YAML with the plugin's documented schema before deploying","Keep each plugin entry in its own clearly indented block to avoid key misplacement"],"tags":["yaml","plugins","validation"],"backgroundTag":"empty-required-field","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"}