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
- Run `nomad plugin status` to list registered plugins and use an existing ID.
- Deploy/run the CSI plugin job so it re-registers: `nomad job run <csi-plugin>.nomad.hcl`.
- Correct the volume's plugin_id and re-register: `nomad volume deregister; nomad volume register`.
- 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
- Cross-check plugin_id against `nomad plugin status` before use.
- Deploy the CSI plugin job before registering volumes that reference it.
- Use consistent plugin IDs via shared config/tooling.
- Verify you target the correct region/cluster.
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
- CSI plugin failed to register: %w
- failed to find instances of controller plugin %q
- no such plugin %q
- error parsing: root should be an object
- missing policy name
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/52dcb4ebb6f5f0ef.
Report an issue: GitHub.