hashicorp/nomad · error

unimplemented for this plugin

Error message

unimplemented for this plugin

What it means

ListExternal returns this when the plugin exists but lacks the controller capability CSIControllerSupportsListVolumes. The error is thrown before any client RPC is attempted: the plugin's reported controller capability set does not include ListVolumes, so listing external volumes via this plugin is unsupported. It is a capability negotiation failure, not a transient error.

Source

Thrown at nomad/csi_endpoint.go:1557

	// NOTE: this is the plugin's namespace, not the volume(s) because they
	// might not even be registered
	if !allowVolume(aclObj, args.RequestNamespace()) {
		return structs.ErrPermissionDenied
	}
	snap, err := v.srv.fsm.State().Snapshot()
	if err != nil {
		return err
	}

	plugin, err := snap.CSIPluginByID(nil, args.PluginID)
	if err != nil {
		return err
	}
	if plugin == nil {
		return fmt.Errorf("no such plugin")
	}
	if !plugin.HasControllerCapability(structs.CSIControllerSupportsListVolumes) {
		return fmt.Errorf("unimplemented for this plugin")
	}

	method := "ClientCSI.ControllerListVolumes"
	cReq := &cstructs.ClientCSIControllerListVolumesRequest{
		MaxEntries:    args.PerPage,
		StartingToken: args.NextToken,
	}
	cReq.PluginID = plugin.ID
	cResp := &cstructs.ClientCSIControllerListVolumesResponse{}

	err = v.srv.RPC(method, cReq, cResp)
	if err != nil {
		return err
	}
	if args.PerPage > 0 && args.PerPage < int32(len(cResp.Entries)) {
		// this should be done in the plugin already, but enforce it
		reply.Volumes = cResp.Entries[:args.PerPage]
	} else {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the plugin supports ListVolumes: inspect the controller job's csi_plugin ControllerCapabilities / the registered plugin's ControllerInfo and use a plugin that advertises ListVolumes
  2. Upgrade the storage driver/plugin to a version that implements the CSI ControllerListVolumes RPC with LIST_VOLUMES controller capability
  3. If the underlying driver genuinely cannot list volumes, manage the volume listing through the vendor's own tooling instead of Nomad's ListExternal endpoint
  4. Re-run the controller plugin registration after upgrading so the capability set is refreshed

Example fix

// before (plugin without ListVolumes capability)
template { csi_plugin { id = "volume-only-plugin" } } // nomad volume list -external -plugin volume-only-plugin
// after
plugin id = "aws-ebs-controller" with CONTROLLER_SERVICES = volume, capability ListVolumes; then: nomad volume list -external -plugin aws-ebs-controller
Defensive patterns

Strategy: validation

Validate before calling

p, _, err := client.Plugins().Get(ctx, pluginID, nil)
if err != nil || p == nil { return err }
if p.ControllerInfo == nil || !p.ControllerInfo.ListVolumes {
    return fmt.Errorf("plugin %q does not support ListVolumes", pluginID)
}

Type guard

func supportsListVolumes(p *api.CSIPlugin) bool {
    return p != nil && p.ControllerInfo != nil && p.ControllerInfo.ListVolumes
}

Try / catch

if err := listExternal(pluginID); err != nil {
    if strings.Contains(err.Error(), "unimplemented for this plugin") {
        return fmt.Errorf("falling back to vendor CLI for volume listing: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ListExternal against a CSI plugin whose ControllerInfo (as advertised during plugin registration) omits ListVolumes support — e.g. a plugin that only supports create/delete/snapshot, or an older plugin version whose registration lacked the ListVolumes capability flag.

Common situations: Using a CSI plugin build/driver that doesn't implement ControllerListVolumes (many storage drivers don't); upgrading the storage driver downgraded capabilities; targeting a plugin that only runs in node-only mode without controller capabilities; invoking `nomad volume list -external` against a volume-only plugin.

Related errors


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