{"record":{"id":"eaa88305ef2c7e53","repo":"docker/cli","slug":"bad-format-for-device-path-s","errorCode":null,"errorMessage":"bad format for device path: %s","messagePattern":"bad format for device path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"opts/throttledevice.go","lineNumber":23,"sourceCode":"\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/docker/go-units\"\n\t\"github.com/moby/moby/api/types/blkiodev\"\n)\n\n// ValidatorThrottleFctType defines a validator function that returns a validated struct and/or an error.\ntype ValidatorThrottleFctType func(val string) (*blkiodev.ThrottleDevice, error)\n\n// ValidateThrottleBpsDevice validates that the specified string has a valid device-rate format.\nfunc ValidateThrottleBpsDevice(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 := units.RAMInBytes(v)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb\", val)\n\t}\n\tif rate < 0 {\n\t\treturn nil, fmt.Errorf(\"invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb\", val)\n\t}\n\n\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, \":\")","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/opts/throttledevice.go#L5-L41","documentation":"Returned by ValidateThrottleBpsDevice when the device-path portion of a --device-read-bps / --device-write-bps value does not start with '/dev/'. The client enforces that device paths reference a /dev node even though the daemon could validate later.","triggerScenarios":"'docker run --device-read-bps=sda:1mb' or '...=dev/sda:1mb' or '...=/sys/block/sda:1mb' — anything whose left-of-colon key lacks the literal '/dev/' prefix.","commonSituations":"Users pass a bare device name ('sda') or a sysfs path instead of a /dev node, assuming Docker resolves the shorthand.","solutions":["Use the full /dev path: '--device-read-bps=/dev/sda:1mb'.","If unsure of the node, list devices with 'ls /dev' or 'lsblk' and copy the /dev/<name> path.","Keep the /dev/ prefix even for NVMe/DM names (e.g. /dev/nvme0n1)."],"exampleFix":"# before\ndocker run --device-read-bps=sda:1mb ubuntu\n# after\ndocker run --device-read-bps=/dev/sda:1mb ubuntu","handlingStrategy":"validation","validationCode":"// Enforce the /dev/ prefix the client requires, before calling the validator.\nimport \"strings\"\n\nfunc hasDevPrefix(s string) bool {\n    k, _, ok := strings.Cut(s, \":\")\n    return ok && strings.HasPrefix(k, \"/dev/\")\n}\n\n// if !hasDevPrefix(val) { return fmt.Errorf(\"device path must start with /dev/: %q\", val) }","typeGuard":null,"tryCatchPattern":"if _, err := opts.ValidateThrottleBpsDevice(val); err != nil {\n    return err // bad format for device path: <val>\n}","preventionTips":["Source device paths from /dev (lsblk gives them with the /dev/ prefix).","Never pass a bare disk name or a /sys path.","Add a unit test mirroring opts/weightdevice_test.go for your wrapper."],"tags":["docker","blkio","throttle","cli","device-path"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}