hashicorp/nomad · error
Plugin.Type must not be empty
Error message
Plugin.Type must not be empty
What it means
dynamicplugins.RegisterPlugin validates PluginInfo before adding it to the registry and persisting it. A plugin with an empty Type field is rejected. The comment states this shouldn't reach a production cluster and exists to aid developers defining new plugin types.
Source
Thrown at client/dynamicplugins/registry.go:174
d.stubDispensers = nil
}
return
}
// setup stubs
if d.stubDispensers == nil {
d.stubDispensers = make(map[string]PluginDispenser, 1)
}
d.stubDispensers[ptype] = dispenser
}
func (d *dynamicRegistry) RegisterPlugin(info *PluginInfo) error {
if info.Type == "" {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return errors.New("Plugin.Type must not be empty")
}
if info.ConnectionInfo == nil {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return errors.New("Plugin.ConnectionInfo must not be nil")
}
if info.Name == "" {
// This error shouldn't make it to a production cluster and is to aid
// developers during the development of new plugin types.
return errors.New("Plugin.Name must not be empty")
}
d.pluginsLock.Lock()
defer d.pluginsLock.Unlock()
pmap, ok := d.plugins[info.Type]View on GitHub (pinned to 482b49bf1a)
Solutions
- Set info.Type (dynamicplugins.PluginTypeCSIController/Node or your custom type) before calling RegisterPlugin
- Use dynamicplugins.NewPluginInfo with all fields populated instead of manual struct construction
- Validate the PluginInfo with info.Validate() first to catch all field problems at once
Example fix
// before
info := &dynamicplugins.PluginInfo{Name: name, ConnectionInfo: connInfo}
registry.RegisterPlugin(info) // error: Plugin.Type must not be empty
// after
info, err := dynamicplugins.NewPluginInfo("csi-controller", name, nil, connInfo, allocID, "v1")
if err != nil { return err }
return registry.RegisterPlugin(info) Defensive patterns
Strategy: validation
Validate before calling
if info == nil || info.Type == "" {
return errors.New("plugin type is required")
}
if err := info.Validate(); err != nil { return err } Type guard
func registrable(info *dynamicplugins.PluginInfo) bool {
return info != nil && info.Type != "" && info.ConnectionInfo != nil && info.Name != ""
} Try / catch
if err := registry.RegisterPlugin(info); err != nil {
if err.Error() == "Plugin.Type must not be empty" {
return fmt.Errorf("plugin %q registered without a type; bug in registration caller", info.Name)
}
return err
} Prevention
- Always construct PluginInfo via NewPluginInfo, not raw literals
- Call info.Validate() before RegisterPlugin
- Define plugin type constants once and reuse them
When it happens
Trigger: Calling RegisterPlugin with a PluginInfo built via NewPluginInfo (or struct literal) where Type is "" — e.g. forgetting to pass the type when constructing from a CSI node registration or config.
Common situations: CSI node registration flows where the plugin type was never set; new plugin-type development (the stated purpose); decoding registry state from an old/partial snapshot.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Plugin.ConnectionInfo must not be nil
- missing secret ID
- CSI.ControllerAttachVolume: VolumeID is required
- CSI.ControllerAttachVolume: ClientCSINodeID is required
- CSI.ControllerDetachVolume: VolumeID is required
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/35ed78e4e3e0c5a9.
Report an issue: GitHub.