hashicorp/nomad · warning

Error querying CSI external volumes for plugin %q: %w

Error message

Error querying CSI external volumes for plugin %q: %w

What it means

When listing external (controller-managed) CSI volumes per plugin via client.CSIVolumes().ListExternal, any error other than io.EOF is appended to a multierror with this message. The loop then skips to the next plugin (NEXT_PLUGIN), so one bad plugin does not abort the whole listing.

Source

Thrown at command/volume_status_csi.go:101

		return fmt.Errorf("Error querying CSI plugins: %w", err)
	}

	if len(plugins) == 0 {
		return nil // No more output if we have no plugins
	}

	var mErr *multierror.Error
	q := &api.QueryOptions{PerPage: 30} // TODO: tune page size

NEXT_PLUGIN:
	for _, plugin := range plugins {
		if !plugin.ControllerRequired || plugin.ControllersHealthy < 1 {
			continue // only controller plugins can support this query
		}
		for {
			externalList, _, err := client.CSIVolumes().ListExternal(plugin.ID, q)
			if err != nil && !errors.Is(err, io.EOF) {
				mErr = multierror.Append(mErr, fmt.Errorf(
					"Error querying CSI external volumes for plugin %q: %w", plugin.ID, err))
				// we'll stop querying this plugin, but there may be more to
				// query, so report and set the error code but move on to the
				// next plugin
				continue NEXT_PLUGIN
			}
			if externalList == nil || len(externalList.Volumes) == 0 {
				// several plugins return EOF once you hit the end of the page,
				// rather than an empty list
				continue NEXT_PLUGIN
			}
			c.Ui.Output("") // force a newline
			rows := []string{"External ID|Condition|Nodes"}
			for _, v := range externalList.Volumes {
				condition := "OK"
				if v.IsAbnormal {
					condition = fmt.Sprintf("Abnormal (%v)", v.Status)
				}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the wrapped error and plugin ID; deregister/redeploy the unhealthy CSI plugin (nomad plugin status, then fix the controller workload)
  2. Check the storage backend/controller reachability from the client node running the plugin
  3. Verify ACL token has volume listing permissions; re-run to see if other plugins listed fine

Example fix

// controller container crashing
// before: plugin registered, ListExternal times out
// after: fix controller deployment, then
nomad plugin status <plugin-id>  # ControllersHealthy >= 1
nomad volume status -verbose
Defensive patterns

Strategy: fallback

Validate before calling

for _, p := range plugins {
    if p.ControllerRequired && p.ControllersHealthy < 1 {
        // plugin will be skipped anyway; pre-warn users
    }
}

Type guard

func controllerCapable(p *api.CSIPluginListStub) bool { return p.ControllerRequired && p.ControllersHealthy >= 1 }

Try / catch

if err := cmd.Run(); err != nil {
    if strings.Contains(err.Error(), "Error querying CSI external volumes") {
        // output may be partial: re-check plugin health before trusting results
    }
}

Prevention

When it happens

Trigger: csiVolumesList (verbose) iterates plugins where ControllerRequired is true and ControllersHealthy >= 1, and ListExternal(plugin.ID, q) returns a non-EOF error: controller RPC failure, plugin socket down, ACL denial, or timeout on the paginated query.

Common situations: A CSI plugin registers as healthy but its controller endpoint is broken (crash-looping controller pod), leaving stale registrations; also tokens lacking volume listing perms. Result is a partial listing plus an aggregated error at exit.

Related errors


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