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

  1. Set info.Type (dynamicplugins.PluginTypeCSIController/Node or your custom type) before calling RegisterPlugin
  2. Use dynamicplugins.NewPluginInfo with all fields populated instead of manual struct construction
  3. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/35ed78e4e3e0c5a9. Report an issue: GitHub.