hashicorp/nomad · error

plugin missing: %s

Error message

plugin missing: %s

What it means

After a successful lookup, if CSIPluginByID returns a nil plugin, clientIDsForController returns 'plugin missing: <id>'. The request named a pluginID that is not registered anywhere in the cluster's state store.

Source

Thrown at nomad/client_csi_endpoint.go:306

	if err != nil {
		return nil, err
	}

	if pluginID == "" {
		return nil, fmt.Errorf("missing plugin ID")
	}

	ws := memdb.NewWatchSet()

	// note: plugin IDs are not scoped to region but volumes are. so any Nomad
	// client we get for a controller is already in the same region for the
	// volume.
	plugin, err := snap.CSIPluginByID(ws, pluginID)
	if err != nil {
		return nil, fmt.Errorf("error getting plugin: %s, %v", pluginID, err)
	}
	if plugin == nil {
		return nil, fmt.Errorf("plugin missing: %s", pluginID)
	}

	clientIDs := []string{}

	if len(plugin.Controllers) == 0 {
		return nil, fmt.Errorf("failed to find instances of controller plugin %q", pluginID)
	}

	var merr error
	for clientID, controller := range plugin.Controllers {
		if !controller.IsController() {
			// we don't have separate types for CSIInfo depending on whether
			// it's a controller or node. this error should never make it to
			// production
			merr = errors.Join(merr, fmt.Errorf(
				"plugin instance %q is not a controller but was registered as one - this is always a bug", controller.AllocID))
			continue
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Run `nomad plugin status` to list registered plugins and use an existing ID.
  2. Deploy/run the CSI plugin job so it re-registers: `nomad job run <csi-plugin>.nomad.hcl`.
  3. Correct the volume's plugin_id and re-register: `nomad volume deregister; nomad volume register`.
  4. Check you are querying the right region/cluster where the plugin is registered.

Example fix

// before: typo in volume spec
plugin_id = "aws-ebs-contoller"   # plugin missing
// after
plugin_id = "aws-ebs-controller"
nomad volume deregister ebs-vol && nomad volume register ebs.hcl
Defensive patterns

Strategy: validation

Validate before calling

plugins, _, _ := client.Plugins().List(nil)
found := false
for _, p := range plugins { if p.ID == wantID { found = true } }
if !found { return fmt.Errorf("plugin %q not registered", wantID) }

Type guard

func pluginRegistered(plugins []*api.CSIPlugin, id string) bool {
    for _, p := range plugins { if p.ID == id { return true } }
    return false
}

Try / catch

err := csi.ControllerListVolumes(args, reply)
if err != nil && strings.Contains(err.Error(), "plugin missing:") {
    return fmt.Errorf("register the plugin job first: %w", err)
}

Prevention

When it happens

Trigger: Controller RPC referencing a pluginID that was never registered, or whose plugin job was deregistered/garbage-collected (plugin deregistration after the plugin job is purged).

Common situations: Typo'd plugin_id in a volume spec; CSI plugin job stopped long enough for the plugin to be deregistered; volume registered in one cluster but used against another; region mismatch where the plugin only runs elsewhere.

Related errors


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