{"record":{"id":"df30425107a55008","repo":"hashicorp/nomad","slug":"targetpath-is-required","errorCode":null,"errorMessage":"TargetPath is required","messagePattern":"TargetPath is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/csi/plugin.go","lineNumber":1060,"sourceCode":"\t\tLimitBytes:    c.LimitBytes,\n\t}\n}\n\ntype NodeExpandVolumeRequest struct {\n\tExternalVolumeID string\n\tCapacityRange    *CapacityRange\n\tCapability       *VolumeCapability\n\tTargetPath       string\n\tStagingPath      string\n}\n\nfunc (r *NodeExpandVolumeRequest) Validate() error {\n\tvar err error\n\tif r.ExternalVolumeID == \"\" {\n\t\terr = errors.Join(err, errors.New(\"ExternalVolumeID is required\"))\n\t}\n\tif r.TargetPath == \"\" {\n\t\terr = errors.Join(err, errors.New(\"TargetPath is required\"))\n\t}\n\tif e := r.CapacityRange.Validate(); e != nil {\n\t\terr = errors.Join(err, e)\n\t}\n\treturn err\n}\n\nfunc (r *NodeExpandVolumeRequest) ToCSIRepresentation() *csipbv1.NodeExpandVolumeRequest {\n\tif r == nil {\n\t\treturn nil\n\t}\n\treturn &csipbv1.NodeExpandVolumeRequest{\n\t\tVolumeId:          r.ExternalVolumeID,\n\t\tVolumePath:        r.TargetPath,\n\t\tStagingTargetPath: r.StagingPath,\n\t\tCapacityRange:     r.CapacityRange.ToCSIRepresentation(),\n\t\tVolumeCapability:  r.Capability.ToCSIRepresentation(),\n\t}","sourceCodeStart":1042,"sourceCodeEnd":1078,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/csi/plugin.go#L1042-L1078","documentation":"NodeExpandVolumeRequest.Validate in plugins/csi/plugin.go:1060 requires TargetPath, the filesystem path on the node where the volume is mounted, because CSI NodeExpandVolume operates on the published mount point. It is emitted (joined alongside any other failures) when TargetPath is empty.","triggerScenarios":"Volume-expand request built without the path where the volume is published on the node; volume is not actually mounted/published so the caller has no target path and leaves it blank.","commonSituations":"Expanding a volume that was never mounted on the node (no alloc using it); custom CSI clients omitting TargetPath; automation that copies the create-request shape (which has no TargetPath) into an expand request.","solutions":["Set TargetPath to the staging/publish mount path of the volume on that node (e.g. /var/lib/nomad/... mount point)","Ensure the volume is actually published (an alloc is using it) before expanding; expansion requires a live mount","Pass the path recorded in the volume's publish state rather than leaving it empty"],"exampleFix":"// before\nerr := client.NodeExpandVolume(volID, capacityRange, \"\")\n// after\nerr := client.NodeExpandVolume(volID, capacityRange, mountPoint) // mountPoint from volume publish status","handlingStrategy":"validation","validationCode":"if req.TargetPath == \"\" { return errors.New(\"TargetPath is required\") }","typeGuard":"func hasTarget(req *csi.NodeExpandVolumeRequest) bool { return req.TargetPath != \"\" }","tryCatchPattern":null,"preventionTips":["Fetch the publish mount path from volume status before expanding","Only expand volumes that are published on the node","Model expand requests distinctly from create requests to avoid missing fields"],"tags":["csi","validation","volume-expand"],"backgroundTag":"missing-required-argument","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"}