{"record":{"id":"7ef28ad7c8bbdca1","repo":"hashicorp/nomad","slug":"controller-expand-volume-v","errorCode":null,"errorMessage":"controller expand volume: %v","messagePattern":"controller expand volume: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/client_csi_endpoint.go","lineNumber":98,"sourceCode":"\t\t\"ClientCSI.ControllerCreateVolume\",\n\t\tstructs.RateMetricWrite,\n\t\targs, reply)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"controller create volume: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (a *ClientCSI) ControllerExpandVolume(args *cstructs.ClientCSIControllerExpandVolumeRequest, reply *cstructs.ClientCSIControllerExpandVolumeResponse) error {\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"client_csi_controller\", \"expand_volume\"}, time.Now())\n\n\terr := a.sendCSIControllerRPC(args.PluginID,\n\t\t\"CSI.ControllerExpandVolume\",\n\t\t\"ClientCSI.ControllerExpandVolume\",\n\t\tstructs.RateMetricWrite,\n\t\targs, reply)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"controller expand volume: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (a *ClientCSI) ControllerDeleteVolume(args *cstructs.ClientCSIControllerDeleteVolumeRequest, reply *cstructs.ClientCSIControllerDeleteVolumeResponse) error {\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"client_csi_controller\", \"delete_volume\"}, time.Now())\n\n\terr := a.sendCSIControllerRPC(args.PluginID,\n\t\t\"CSI.ControllerDeleteVolume\",\n\t\t\"ClientCSI.ControllerDeleteVolume\",\n\t\tstructs.RateMetricWrite,\n\t\targs, reply)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"controller delete volume: %v\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/client_csi_endpoint.go#L80-L116","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Confirm the new size is >= current size; CSI cannot shrink — create a larger volume instead if shrinking is needed.","Check the plugin advertises expand capability (`nomad plugin status`) and that expansion is supported online; detach/stop workloads if the backend requires offline expansion.","Inspect plugin logs for the backend error, fix storage-side constraints (quota, snapshot in progress), then retry re-registration of the volume."],"exampleFix":"# before: shrink attempt (not supported)\nvolume \"db\" { capacity_min = \"5GiB\" capacity_max = \"5GiB\" }  # was 10GiB\n# after: only grow\nvolume \"db\" { capacity_min = \"20GiB\" capacity_max = \"20GiB\" }","handlingStrategy":"validation","validationCode":"const vol = await nomad.volume(volumeID)\nif (newSizeBytes < currentCapacityBytes(vol)) {\n  throw new Error('CSI expansion cannot shrink; provision a new larger volume instead')\n}\nconst plugin = await nomad.plugin(vol.pluginID)\nif (!(plugin.controllerCapabilities ?? []).includes('EXPAND_VOLUME')) {\n  throw new Error('controller does not support expansion')\n}","typeGuard":"const canExpand = (p) => (p.controllerCapabilities ?? []).includes('EXPAND_VOLUME')","tryCatchPattern":"try { await resizeVolume(volumeID, newSize) }\ncatch (e) {\n  if (String(e).startsWith('controller expand volume')) {\n    log.error('expansion rejected:', e)\n    return { expanded: false, requiresOffline: true }\n  }\n  throw e\n}","preventionTips":["Only ever grow volumes; plan migrations for shrink needs.","Check whether the backend supports online (attached) expansion; stop workloads if not.","Confirm EXPAND_VOLUME controller capability after plugin upgrades.","Watch backend constraints: snapshots or quotas can block expansion."],"tags":["nomad","csi","storage","expansion","plugin"],"backgroundTag":"csi-controller-rpc-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}