hashicorp/nomad · error
nil config passed for internal plugin %s
Error message
nil config passed for internal plugin %s
What it means
Each entry in config.InternalPlugins maps a plugin name to an *InternalPluginConfig. validateConfig appends this error (per named plugin) when the map value is nil, since fingerprinting an internal plugin requires its Factory and Config.
Source
Thrown at helper/pluginutils/loader/init.go:44
var mErr multierror.Error
if config == nil {
return fmt.Errorf("nil config passed")
} else if config.Logger == nil {
_ = multierror.Append(&mErr, fmt.Errorf("nil logger passed"))
}
// Validate that all plugins have a binary name
for _, c := range config.Configs {
if c.Name == "" {
_ = multierror.Append(&mErr, fmt.Errorf("plugin config passed without binary name"))
}
}
// Validate internal plugins
for k, config := range config.InternalPlugins {
// Validate config
if config == nil {
_ = multierror.Append(&mErr, fmt.Errorf("nil config passed for internal plugin %s", k))
continue
} else if config.Factory == nil {
_ = multierror.Append(&mErr, fmt.Errorf("nil factory passed for internal plugin %s", k))
continue
}
}
return mErr.ErrorOrNil()
}
// init initializes the plugin loader by compiling both internal and external
// plugins and selecting the highest versioned version of any given plugin.
func (l *PluginLoader) init(cfg *PluginLoaderConfig) (map[string]*config.PluginConfig, error) {
// Create a mapping of name to config
configMap := configMap(cfg.Configs)
// Initialize the internal plugins
internal, err := l.initInternal(cfg.InternalPlugins, configMap)View on GitHub (pinned to 482b49bf1a)
Solutions
- Provide a complete *InternalPluginConfig (with Factory set) for every key in InternalPlugins.
- Remove map entries whose config could not be built instead of inserting nil.
- Add a pre-registration check that skips/logs nil configs before calling NewPluginLoader.
Example fix
// before
internal := map[string]*InternalPluginConfig{"exec": nil}
// after
internal := map[string]*InternalPluginConfig{
"exec": {Factory: exec.NewPlugin, Config: &config.Config{}},
} Defensive patterns
Strategy: validation
Validate before calling
for name, ipc := range cfg.InternalPlugins {
if ipc == nil {
return fmt.Errorf("internal plugin %q has nil config", name)
}
}
loader, err := NewPluginLoader(cfg) Type guard
func validInternalPlugins(m map[string]*InternalPluginConfig) bool {
for k, v := range m {
if v == nil || v.Factory == nil {
_ = k
return false
}
}
return true
} Try / catch
loader, err := NewPluginLoader(cfg)
if err != nil {
if strings.Contains(err.Error(), "nil config passed for internal plugin") {
return fmt.Errorf("bad internal plugin registration: %w", err)
}
return err
} Prevention
- Only insert into InternalPlugins after the config object is fully constructed.
- Skip (don't insert) optional plugins whose construction failed.
- Cover internal-plugin registration in unit tests.
When it happens
Trigger: Populating InternalPlugins with a key but a nil value, e.g. map["my-plugin"] = nil, or declaring a variable of *InternalPluginConfig that was never assigned before insertion.
Common situations: Conditional registration code that allocates the config only under some branch; refactor where the factory/config construction was deleted but the map insertion remained; test scaffolding that stubs map keys.
Related errors
- nil config passed
- plugin config passed without binary name
- nil factory passed for internal plugin %s
- parsing plugin configurations failed: %v
- ErrPluginNotExecutable
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d47b7492e5abee1f.
Report an issue: GitHub.