hashicorp/nomad · error

controller expand volume: %v

Error message

controller expand volume: %v

What it means

ClientCSI.ControllerExpandVolume forwards a CSI ControllerExpandVolume RPC to the controller plugin and wraps failures as "controller expand volume: <err>". It is used by the CSI volume expansion workflow when a registered volume's requested capacity is raised.

Source

Thrown at nomad/client_csi_endpoint.go:98

		"ClientCSI.ControllerCreateVolume",
		structs.RateMetricWrite,
		args, reply)
	if err != nil {
		return fmt.Errorf("controller create volume: %v", err)
	}
	return nil
}

func (a *ClientCSI) ControllerExpandVolume(args *cstructs.ClientCSIControllerExpandVolumeRequest, reply *cstructs.ClientCSIControllerExpandVolumeResponse) error {
	defer metrics.MeasureSince([]string{"nomad", "client_csi_controller", "expand_volume"}, time.Now())

	err := a.sendCSIControllerRPC(args.PluginID,
		"CSI.ControllerExpandVolume",
		"ClientCSI.ControllerExpandVolume",
		structs.RateMetricWrite,
		args, reply)
	if err != nil {
		return fmt.Errorf("controller expand volume: %v", err)
	}
	return nil
}

func (a *ClientCSI) ControllerDeleteVolume(args *cstructs.ClientCSIControllerDeleteVolumeRequest, reply *cstructs.ClientCSIControllerDeleteVolumeResponse) error {
	defer metrics.MeasureSince([]string{"nomad", "client_csi_controller", "delete_volume"}, time.Now())

	err := a.sendCSIControllerRPC(args.PluginID,
		"CSI.ControllerDeleteVolume",
		"ClientCSI.ControllerDeleteVolume",
		structs.RateMetricWrite,
		args, reply)
	if err != nil {
		return fmt.Errorf("controller delete volume: %v", err)
	}
	return nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Confirm the new size is >= current size; CSI cannot shrink — create a larger volume instead if shrinking is needed.
  2. Check the plugin advertises expand capability (`nomad plugin status`) and that expansion is supported online; detach/stop workloads if the backend requires offline expansion.
  3. Inspect plugin logs for the backend error, fix storage-side constraints (quota, snapshot in progress), then retry re-registration of the volume.

Example fix

# before: shrink attempt (not supported)
volume "db" { capacity_min = "5GiB" capacity_max = "5GiB" }  # was 10GiB
# after: only grow
volume "db" { capacity_min = "20GiB" capacity_max = "20GiB" }
Defensive patterns

Strategy: validation

Validate before calling

const vol = await nomad.volume(volumeID)
if (newSizeBytes < currentCapacityBytes(vol)) {
  throw new Error('CSI expansion cannot shrink; provision a new larger volume instead')
}
const plugin = await nomad.plugin(vol.pluginID)
if (!(plugin.controllerCapabilities ?? []).includes('EXPAND_VOLUME')) {
  throw new Error('controller does not support expansion')
}

Type guard

const canExpand = (p) => (p.controllerCapabilities ?? []).includes('EXPAND_VOLUME')

Try / catch

try { await resizeVolume(volumeID, newSize) }
catch (e) {
  if (String(e).startsWith('controller expand volume')) {
    log.error('expansion rejected:', e)
    return { expanded: false, requiresOffline: true }
  }
  throw e
}

Prevention

When it happens

Trigger: Increasing capacity_min/capacity_max on a registered CSI volume and re-registering, when the controller plugin is unavailable or the backend rejects expansion (volume in use, shrink not allowed, capability unsupported).

Common situations: Trying to shrink a volume (CSI only supports growth); backend does not support online expansion while the volume is attached; controller plugin lacks EXPAND_VOLUME capability; plugin down.

Related errors


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