{"record":{"id":"67c56426000be67d","repo":"hashicorp/nomad","slug":"plugin-config-passed-without-binary-name","errorCode":null,"errorMessage":"plugin config passed without binary name","messagePattern":"plugin config passed without binary name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/init.go","lineNumber":36,"sourceCode":"\t\"github.com/hashicorp/nomad/helper/pluginutils/hclutils\"\n\t\"github.com/hashicorp/nomad/nomad/structs/config\"\n\t\"github.com/hashicorp/nomad/plugins/base\"\n\t\"github.com/zclconf/go-cty/cty/msgpack\"\n)\n\n// validateConfig returns whether or not the configuration is valid\nfunc validateConfig(config *PluginLoaderConfig) error {\n\tvar mErr multierror.Error\n\tif config == nil {\n\t\treturn fmt.Errorf(\"nil config passed\")\n\t} else if config.Logger == nil {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"nil logger passed\"))\n\t}\n\n\t// Validate that all plugins have a binary name\n\tfor _, c := range config.Configs {\n\t\tif c.Name == \"\" {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"plugin config passed without binary name\"))\n\t\t}\n\t}\n\n\t// Validate internal plugins\n\tfor k, config := range config.InternalPlugins {\n\t\t// Validate config\n\t\tif config == nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"nil config passed for internal plugin %s\", k))\n\t\t\tcontinue\n\t\t} else if config.Factory == nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"nil factory passed for internal plugin %s\", k))\n\t\t\tcontinue\n\t\t}\n\t}\n\n\treturn mErr.ErrorOrNil()\n}\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/init.go#L18-L54","documentation":"Every external plugin entry in config.Configs must have a Name identifying the plugin binary. validateConfig iterates the slice and appends this error to a multierror for each entry with an empty Name, because the loader cannot match scanned binaries to configs without it.","triggerScenarios":"Appending &PluginConfig{} or &PluginConfig{Config: ...} to Configs without setting Name; building configs in a loop where the name variable was empty.","commonSituations":"Plugin config assembled from environment or CLI flags where the plugin-name flag was missing; YAML/JSON config decoding into PluginConfig where the name key was absent; copy-paste of a config entry with the name removed.","solutions":["Set Name on each PluginConfig to the plugin binary's base name (e.g. \"nomad-device-nvidia\").","Add a startup-time check that filters or rejects config entries with empty names before building the loader config.","Fix the upstream config source (file/env/flags) so the name is always provided."],"exampleFix":"// before\nconfigs := []*PluginConfig{{Config: map[string]interface{}{\"foo\": \"bar\"}}}\n\n// after\nconfigs := []*PluginConfig{{Name: \"nomad-driver-docker\", Config: map[string]interface{}{\"foo\": \"bar\"}}}","handlingStrategy":"validation","validationCode":"for i, c := range cfg.Configs {\n    if c.Name == \"\" {\n        return fmt.Errorf(\"configs[%d]: missing plugin binary name\", i)\n    }\n}\nloader, err := NewPluginLoader(cfg)","typeGuard":"func validPluginConfigs(cfgs []*PluginConfig) bool {\n    for _, c := range cfgs {\n        if c == nil || c.Name == \"\" {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"loader, err := NewPluginLoader(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"without binary name\") {\n        return fmt.Errorf(\"plugin config incomplete: %w\", err)\n    }\n    return err\n}","preventionTips":["Parse plugin configs from a single schema-validated source with required-field checks.","Validate config structs right after decoding from file/env, not at loader construction.","Name entries after the actual binary file names in the plugin dir."],"tags":["go","configuration","validation","plugins"],"backgroundTag":"missing-required-argument","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}