{"record":{"id":"1e2e27a106c26937","repo":"hashicorp/nomad","slug":"pluginid-is-required","errorCode":null,"errorMessage":"PluginID is required","messagePattern":"PluginID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/structs/csi.go","lineNumber":481,"sourceCode":"\tPluginID        string // ID of the plugin that manages the volume (required)\n\tVolumeID        string // ID of the volume to be expanded (required)\n\tVolumeNamespace string // Namespace of the volume to be expanded (required)\n\tExternalID      string // External ID of the volume to be expanded (required)\n\n\t// Capacity range (required) to be sent to the node plugin\n\tCapacity *csi.CapacityRange\n\n\t// Claim currently held for the allocation (required)\n\t// used to determine capabilities and the mount point on the client\n\tClaim *structs.CSIVolumeClaim\n}\n\nfunc (req *ClientCSINodeExpandVolumeRequest) Validate() error {\n\tvar err error\n\t// These should not occur during normal operations; they're here\n\t// mainly to catch potential programmer error.\n\tif req.PluginID == \"\" {\n\t\terr = errors.Join(err, errors.New(\"PluginID is required\"))\n\t}\n\tif req.VolumeID == \"\" {\n\t\terr = errors.Join(err, errors.New(\"VolumeID is required\"))\n\t}\n\tif req.ExternalID == \"\" {\n\t\terr = errors.Join(err, errors.New(\"ExternalID is required\"))\n\t}\n\tif req.Claim == nil {\n\t\terr = errors.Join(err, errors.New(\"Claim is required\"))\n\t} else if req.Claim.AllocationID == \"\" {\n\t\terr = errors.Join(err, errors.New(\"Claim.AllocationID is required\"))\n\t}\n\treturn err\n}\n\ntype ClientCSINodeExpandVolumeResponse struct {\n\tCapacityBytes int64\n}","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/structs/csi.go#L463-L499","documentation":"err(\"PluginID is required\") is produced by ClientCSINodeExpandVolumeRequest.Validate when the PluginID field is empty. Per the source comment these checks exist mainly to catch programmer error, since a client CSI node expand request without a plugin ID is meaningless. The error is joined via errors.Join with other validation failures.","triggerScenarios":"Submitting a ClientCSINodeExpandVolumeRequest with PluginID == \"\" — e.g. a code path constructing the request that failed to look up the CSI plugin ID for the node.","commonSituations":"Programmer error building the request, plugin deregistration between volume claim and expand so the plugin ID lookup returns empty, or copying the request struct without setting PluginID.","solutions":["Set PluginID from the volume's plugin info before calling the expand RPC","Verify the CSI plugin is registered/running on the node and its ID is resolved","Use errors.Is / string matching on Validate's joined error to identify the missing field","Add a pre-call check that req.PluginID != \"\""],"exampleFix":"// before\nreq := &cstructs.ClientCSINodeExpandVolumeRequest{VolumeID: volID, ExternalID: extID}\n// after\nreq := &cstructs.ClientCSINodeExpandVolumeRequest{PluginID: pluginID, VolumeID: volID, ExternalID: extID}","handlingStrategy":"validation","validationCode":"if err := req.Validate(); err != nil { return err }\nif req.PluginID == \"\" { return errors.New(\"PluginID must be resolved before node expand\") }","typeGuard":null,"tryCatchPattern":"if err := req.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"PluginID is required\") {\n        // re-resolve the CSI plugin ID for the node and rebuild the request\n        return resolvePluginAndRetry()\n    }\n    return err\n}","preventionTips":["Always resolve and set PluginID from the volume's plugin info before the RPC","Verify the CSI plugin is registered on the node before expanding volumes","Run Validate() early and log the joined error for full diagnosis","Add unit tests asserting all request fields are populated"],"tags":["go","csi","validation"],"backgroundTag":"schema-validation-failed","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"}