{"record":{"id":"77536766cb0cf5a8","repo":"hashicorp/nomad","slug":"externalid-is-required","errorCode":null,"errorMessage":"ExternalID is required","messagePattern":"ExternalID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/structs/csi.go","lineNumber":487,"sourceCode":"\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}\n","sourceCodeStart":469,"sourceCodeEnd":500,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/structs/csi.go#L469-L500","documentation":"err(\"ExternalID is required\") is produced by ClientCSINodeExpandVolumeRequest.Validate when the ExternalID field (the storage-provider-side volume ID on the external CSI storage system) is empty. It is another programmer-error guard, joined with other validation errors via errors.Join.","triggerScenarios":"Submitting a ClientCSINodeExpandVolumeRequest with ExternalID == \"\" — the remote/external volume ID was never populated from the controller's response or was lost during request construction.","commonSituations":"Volume created without successful ControllerPublishVolume/external ID sync, partially published volumes, or bugs copying the Nomad volume struct into the client request.","solutions":["Populate ExternalID from the volume's remote/external ID (volume.RemoteID()) before the RPC","Verify the volume was fully created/published on the external storage system","Add a pre-call check that req.ExternalID != \"\"","Inspect the joined Validate error to catch all missing fields at once"],"exampleFix":"// before\nreq := &cstructs.ClientCSINodeExpandVolumeRequest{PluginID: pluginID, VolumeID: vol.ID}\n// after\nreq := &cstructs.ClientCSINodeExpandVolumeRequest{PluginID: pluginID, VolumeID: vol.ID, ExternalID: vol.RemoteID()}","handlingStrategy":"validation","validationCode":"if err := req.Validate(); err != nil { return err }\nif req.ExternalID == \"\" { return errors.New(\"ExternalID (remote volume ID) must be set\") }","typeGuard":null,"tryCatchPattern":"if err := req.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"ExternalID is required\") {\n        // query the controller for the remote volume ID, then retry\n        return resolveExternalIDAndRetry()\n    }\n    return err\n}","preventionTips":["Populate ExternalID via volume.RemoteID() from the controller publish result","Ensure the volume was fully published on external storage before expanding","Run Validate() and inspect the joined error for all missing fields","Test end-to-end create->publish->expand flows after CSI driver changes"],"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"}