{"record":{"id":"6e1e4291b175fb74","repo":"hashicorp/nomad","slug":"one-of-limitbytes-or-requiredbytes-must-be-set-if","errorCode":null,"errorMessage":"one of LimitBytes or RequiredBytes must be set if CapacityRange is set","messagePattern":"one of LimitBytes or RequiredBytes must be set if CapacityRange is set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/csi/plugin.go","lineNumber":501,"sourceCode":"\t\tParameters:                r.Parameters,\n\t\tSecrets:                   r.Secrets,\n\t\tVolumeContentSource:       r.ContentSource.ToCSIRepresentation(),\n\t\tAccessibilityRequirements: r.AccessibilityRequirements.ToCSIRepresentation(),\n\t}\n\n\treturn req\n}\n\nfunc (r *ControllerCreateVolumeRequest) Validate() error {\n\tif r.Name == \"\" {\n\t\treturn errors.New(\"missing Name\")\n\t}\n\tif r.VolumeCapabilities == nil {\n\t\treturn errors.New(\"missing VolumeCapabilities\")\n\t}\n\tif r.CapacityRange != nil {\n\t\tif r.CapacityRange.LimitBytes == 0 && r.CapacityRange.RequiredBytes == 0 {\n\t\t\treturn errors.New(\n\t\t\t\t\"one of LimitBytes or RequiredBytes must be set if CapacityRange is set\")\n\t\t}\n\t\tif r.CapacityRange.LimitBytes > 0 &&\n\t\t\tr.CapacityRange.LimitBytes < r.CapacityRange.RequiredBytes {\n\t\t\treturn errors.New(\"LimitBytes cannot be less than RequiredBytes\")\n\t\t}\n\t}\n\tif r.ContentSource != nil {\n\t\tif r.ContentSource.CloneID != \"\" && r.ContentSource.SnapshotID != \"\" {\n\t\t\treturn errors.New(\n\t\t\t\t\"one of SnapshotID or CloneID must be set if ContentSource is set\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// VolumeContentSource is snapshot or volume that the plugin will use to\n// create the new volume. At most one of these fields can be set, but nil (and","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/csi/plugin.go#L483-L519","documentation":"ControllerCreateVolumeRequest.Validate() rejects a CapacityRange where both LimitBytes and RequiredBytes are zero. If you declare a capacity range at all, it must contain at least one meaningful bound; an all-zero range conveys no constraint and is treated as a caller bug.","triggerScenarios":"Setting CapacityRange to &csi.CapacityRange{} (or a struct populated from config where both size fields rendered as 0) and then calling ControllerCreateVolume.","commonSituations":"Config parsing that failed to convert a human size (e.g. \"10Gi\") into bytes, silently yielding zeros; template typos like required_bytes vs requiredBytes; callers copying the CapacityRange pointer without its values.","solutions":["Set at least one of RequiredBytes or LimitBytes to a positive byte value in the CapacityRange","If no capacity constraint is intended, leave CapacityRange nil instead of passing an empty struct","Check the config-to-bytes conversion for the volume size setting"],"exampleFix":"// before\nreq := &csi.ControllerCreateVolumeRequest{\n    Name:               \"vol-1\",\n    VolumeCapabilities: caps,\n    CapacityRange:      &csi.CapacityRange{}, // both zero -> error\n}\n// after\nreq := &csi.ControllerCreateVolumeRequest{\n    Name:               \"vol-1\",\n    VolumeCapabilities: caps,\n    CapacityRange:      &csi.CapacityRange{RequiredBytes: 10 * 1024 * 1024 * 1024},\n}","handlingStrategy":"validation","validationCode":"func validateCapacity(req *csi.ControllerCreateVolumeRequest) error {\n    cr := req.CapacityRange\n    if cr != nil && cr.LimitBytes == 0 && cr.RequiredBytes == 0 {\n        return errors.New(\"CapacityRange set but both LimitBytes and RequiredBytes are zero\")\n    }\n    return nil\n}","typeGuard":"func hasUsableCapacity(req *csi.ControllerCreateVolumeRequest) bool {\n    cr := req.CapacityRange\n    return cr == nil || cr.LimitBytes > 0 || cr.RequiredBytes > 0\n}","tryCatchPattern":"if err := req.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"LimitBytes or RequiredBytes\") {\n        return fmt.Errorf(\"create refused: set a positive byte value or omit CapacityRange entirely: %w\", err)\n    }\n    return err\n}","preventionTips":["Convert human-readable sizes to bytes with a tested helper and reject zero results","Pass nil CapacityRange when no size constraint is intended","Add a unit test for each size configuration path to catch silent zero conversions"],"tags":["csi","validation","go","storage","capacity"],"backgroundTag":"csi-request-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"}