{"record":{"id":"a1f58cb680a513a6","repo":"docker/cli","slug":"invalid-rate-for-device-s-the-correct-format-is-a1f58c","errorCode":null,"errorMessage":"invalid rate for device: %s. The correct format is <device-path>:<number>. Number must be a positive integer","messagePattern":"invalid rate for device: (.+?)\\. The correct format is <device-path>:<number>\\. Number must be a positive integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"opts/throttledevice.go","lineNumber":51,"sourceCode":"\treturn &blkiodev.ThrottleDevice{\n\t\tPath: k,\n\t\tRate: uint64(rate),\n\t}, nil\n}\n\n// ValidateThrottleIOpsDevice validates that the specified string has a valid device-rate format.\nfunc ValidateThrottleIOpsDevice(val string) (*blkiodev.ThrottleDevice, error) {\n\tk, v, ok := strings.Cut(val, \":\")\n\tif !ok || k == \"\" {\n\t\treturn nil, fmt.Errorf(\"bad format: %s\", val)\n\t}\n\t// TODO(thaJeztah): should we really validate this on the client?\n\tif !strings.HasPrefix(k, \"/dev/\") {\n\t\treturn nil, fmt.Errorf(\"bad format for device path: %s\", val)\n\t}\n\trate, err := strconv.ParseUint(v, 10, 64)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid rate for device: %s. The correct format is <device-path>:<number>. Number must be a positive integer\", val)\n\t}\n\n\treturn &blkiodev.ThrottleDevice{Path: k, Rate: rate}, nil\n}\n\n// ThrottledeviceOpt defines a map of ThrottleDevices\ntype ThrottledeviceOpt struct {\n\tvalues    []*blkiodev.ThrottleDevice\n\tvalidator ValidatorThrottleFctType\n}\n\n// NewThrottledeviceOpt creates a new ThrottledeviceOpt\nfunc NewThrottledeviceOpt(validator ValidatorThrottleFctType) ThrottledeviceOpt {\n\treturn ThrottledeviceOpt{\n\t\tvalues:    []*blkiodev.ThrottleDevice{},\n\t\tvalidator: validator,\n\t}\n}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/opts/throttledevice.go#L33-L69","documentation":"Returned by ValidateThrottleIOpsDevice when strconv.ParseUint(v, 10, 64) fails on the rate part of a --device-read-iops / --device-write-iops value. The iops rate MUST be a base-10 positive integer — no unit suffix, no decimal, no sign.","triggerScenarios":"'docker run --device-read-iops=/dev/sda:1mb' (most common: copying a bps-style unit suffix onto an iops flag), '...=/dev/sda:1.5k', '...=/dev/sda:-100', '...=/dev/sda:' (empty), or any non-numeric value.","commonSituations":"Users assume iops flags accept the same kb/mb/gb suffixes as the bps flags; they do not. Also triggered by env-var substitution that injects a suffix or empty string.","solutions":["Use a plain positive integer: '--device-read-iops=/dev/sda:1000'.","Drop any unit suffix — iops is a unitless count per second.","Ensure substituted values are digits only (strip suffixes/non-digits)."],"exampleFix":"# before\ndocker run --device-read-iops=/dev/sda:1mb ubuntu\n# after\ndocker run --device-read-iops=/dev/sda:1000 ubuntu","handlingStrategy":"validation","validationCode":"// iops rate must be a base-10 unsigned integer (no unit) — check before validating.\nimport (\"strconv\"; \"strings\")\n\nfunc validIops(s string) bool {\n    _, v, ok := strings.Cut(s, \":\")\n    if !ok { return false }\n    _, err := strconv.ParseUint(v, 10, 64)\n    return err == nil\n}\n\n// if !validIops(val) { return fmt.Errorf(\"iops must be a positive integer, got %q\", val) }","typeGuard":null,"tryCatchPattern":"if _, err := opts.ValidateThrottleIOpsDevice(val); err != nil {\n    return err // invalid rate for device: <val> ...\n}","preventionTips":["Never append kb/mb/gb to an iops value — it is a unitless count.","Strip suffixes from substituted values before passing.","Remember: bps flags accept units, iops flags do not."],"tags":["docker","blkio","throttle","iops","cli"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}