{"record":{"id":"8b2bd69c1189f691","repo":"hashicorp/nomad","slug":"csi-controllervalidatevolume-pluginid-is-required","errorCode":null,"errorMessage":"CSI.ControllerValidateVolume: PluginID is required","messagePattern":"CSI\\.ControllerValidateVolume: PluginID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/csi_endpoint.go","lineNumber":50,"sourceCode":"\tCSIPluginRequestTimeout = 2 * time.Minute\n)\n\nvar (\n\tErrPluginTypeError = errors.New(\"CSI Plugin loaded incorrectly\")\n)\n\n// ControllerValidateVolume is used during volume registration to validate\n// that a volume exists and that the capabilities it was registered with are\n// supported by the CSI Plugin and external volume configuration.\nfunc (c *CSI) ControllerValidateVolume(req *structs.ClientCSIControllerValidateVolumeRequest, resp *structs.ClientCSIControllerValidateVolumeResponse) error {\n\tdefer metrics.MeasureSince([]string{\"client\", \"csi_controller\", \"validate_volume\"}, time.Now())\n\n\tif req.VolumeID == \"\" {\n\t\treturn errors.New(\"CSI.ControllerValidateVolume: VolumeID is required\")\n\t}\n\n\tif req.PluginID == \"\" {\n\t\treturn errors.New(\"CSI.ControllerValidateVolume: PluginID is required\")\n\t}\n\n\tplugin, err := c.findControllerPlugin(req.PluginID)\n\tif err != nil {\n\t\t// the server's view of the plugin health is stale, so let it know it\n\t\t// should retry with another controller instance\n\t\treturn fmt.Errorf(\"CSI.ControllerValidateVolume: %w: %v\",\n\t\t\tnstructs.ErrCSIClientRPCRetryable, err)\n\t}\n\tdefer plugin.Close()\n\n\tcsiReq, err := req.ToCSIRequest()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"CSI.ControllerValidateVolume: %v\", err)\n\t}\n\n\tctx, cancelFn := c.requestContext()\n\tdefer cancelFn()","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/csi_endpoint.go#L32-L68","documentation":"ControllerValidateVolume also requires a PluginID to know which CSI controller plugin to route the validation to. An empty PluginID fails this check before any plugin lookup happens. The error is returned immediately after the VolumeID check.","triggerScenarios":"Calling ControllerValidateVolume (or sending a ClientCSIControllerValidateVolumeRequest) with req.PluginID == \"\".","commonSituations":"Volume registration flow where the plugin ID failed to resolve from the volume's plugin provider field; client built the request from a spec where plugin_id/provider was empty; typo in the plugin name resolution that yielded an empty string.","solutions":["Set req.PluginID to the CSI plugin's ID before the request","Ensure the volume/registration flow resolved the plugin ID (e.g. volume.PluginID) and propagated it","Guard client-side: check PluginID non-empty before calling validate-volume"],"exampleFix":"// before\nreq := &structs.ClientCSIControllerValidateVolumeRequest{VolumeID: volumeID}\nc.CSI.ControllerValidateVolume(req, resp) // PluginID is required\n// after\nreq := &structs.ClientCSIControllerValidateVolumeRequest{VolumeID: volumeID, PluginID: volume.PluginID, VolumeCapabilities: caps}\nc.CSI.ControllerValidateVolume(req, resp)","handlingStrategy":"validation","validationCode":"if req.PluginID == \"\" {\n    return fmt.Errorf(\"cannot validate volume: PluginID is empty; ensure the volume's plugin/provider is set\")\n}","typeGuard":"func validValidateVolumeRequest(req *structs.ClientCSIControllerValidateVolumeRequest) bool {\n    return req != nil && req.VolumeID != \"\" && req.PluginID != \"\"\n}","tryCatchPattern":"if err := c.CSI.ControllerValidateVolume(req, resp); err != nil {\n    if strings.Contains(err.Error(), \"PluginID is required\") {\n        return fmt.Errorf(\"plugin ID unresolved before validation: %w\", err)\n    }\n    return err\n}","preventionTips":["Set plugin_id/provider on the volume spec so PluginID resolves during registration","Reuse the same plugin ID resolution helper for all CSI calls","Fail fast on empty plugin resolution instead of issuing the RPC","Add unit tests covering the empty-PluginID request path"],"tags":["csi","validation","plugin","request"],"backgroundTag":"missing-required-request-field","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}