{"record":{"id":"20037f69350ca265","repo":"hashicorp/nomad","slug":"one-of-limitbytes-or-requiredbytes-must-be-set","errorCode":null,"errorMessage":"one of LimitBytes or RequiredBytes must be set","messagePattern":"one of LimitBytes or RequiredBytes must be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/csi/plugin.go","lineNumber":651,"sourceCode":"\t\treturn errors.New(\"missing ExternalVolumeID\")\n\t}\n\treturn nil\n}\n\ntype ControllerExpandVolumeRequest struct {\n\tExternalVolumeID string\n\tRequiredBytes    int64\n\tLimitBytes       int64\n\tCapability       *VolumeCapability\n\tSecrets          structs.CSISecrets\n}\n\nfunc (r *ControllerExpandVolumeRequest) Validate() error {\n\tif r.ExternalVolumeID == \"\" {\n\t\treturn errors.New(\"missing ExternalVolumeID\")\n\t}\n\tif r.LimitBytes == 0 && r.RequiredBytes == 0 {\n\t\treturn errors.New(\"one of LimitBytes or RequiredBytes must be set\")\n\t}\n\t// per the spec: \"A value of 0 is equal to an unspecified field value.\"\n\t// so in this case, only error if both are set.\n\tif r.LimitBytes > 0 && (r.LimitBytes < r.RequiredBytes) {\n\t\treturn errors.New(\"LimitBytes cannot be less than RequiredBytes\")\n\t}\n\treturn nil\n}\n\nfunc (r *ControllerExpandVolumeRequest) ToCSIRepresentation() *csipbv1.ControllerExpandVolumeRequest {\n\tif r == nil {\n\t\treturn nil\n\t}\n\treturn &csipbv1.ControllerExpandVolumeRequest{\n\t\tVolumeId: r.ExternalVolumeID,\n\t\tCapacityRange: &csipbv1.CapacityRange{\n\t\t\tRequiredBytes: r.RequiredBytes,\n\t\t\tLimitBytes:    r.LimitBytes,","sourceCodeStart":633,"sourceCodeEnd":669,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/csi/plugin.go#L633-L669","documentation":"This error is returned by ControllerExpandVolumeRequest.Validate when both LimitBytes and RequiredBytes are 0. A CSI expansion must state a target capacity; since per the spec a value of 0 means 'unspecified', an expand request with no capacity at all is ambiguous and rejected locally before the gRPC call.","triggerScenarios":"Calling ControllerExpandVolume with {ExternalVolumeID: \"vol-1\"} but neither RequiredBytes nor LimitBytes set — e.g. the new size was lost during request construction or the CLI parsed no capacity argument.","commonSituations":"Automation submitting an expand job with an empty capacity template; a CLI flag (--capacity) omitted so 0 is passed through; code that copies only the external ID from the old request and forgets the new capacity fields.","solutions":["Set RequiredBytes (the minimum new capacity) on the expand request.","Optionally also set LimitBytes >= RequiredBytes if the provider needs an acceptable range.","Fix the CLI/config plumbing so the new capacity value reaches the request.","Add a pre-call guard: if RequiredBytes == 0 && LimitBytes == 0, refuse to build the request."],"exampleFix":"// before\nreq := &ControllerExpandVolumeRequest{ExternalVolumeID: id}\n// after\nreq := &ControllerExpandVolumeRequest{\n  ExternalVolumeID: id,\n  RequiredBytes:    20 * 1024 * 1024 * 1024,\n}","handlingStrategy":"validation","validationCode":"if req.RequiredBytes == 0 && req.LimitBytes == 0 {\n\treturn fmt.Errorf(\"expand requires a target capacity: set RequiredBytes\")\n}","typeGuard":"func hasCapacity(r *ControllerExpandVolumeRequest) bool {\n\treturn r != nil && (r.RequiredBytes != 0 || r.LimitBytes != 0)\n}","tryCatchPattern":null,"preventionTips":["Always supply the new size explicitly when scaling a volume.","Make capacity a required CLI/config parameter rather than defaulting to 0.","Unit-test request builders to assert non-zero capacity is set."],"tags":["csi","validation","missing-field","storage","volume-expansion"],"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"}