docker/cli · error
invalid storage option
Error message
invalid storage option
What it means
Thrown by parseStorageOpts when a --storage-opt entry has no '=' separator and thus cannot be split into key=value. The function uses strings.Cut on '=' and errors if the delimiter is absent. Storage options must always be key=value pairs (e.g. size=10G).
Solutions
- Rewrite the option as key=value: `--storage-opt size=10G`.
- Check shell quoting around values containing '=' or special chars; quote the whole pair.
- Refer to the driver's accepted keys (overlay2: size; devicemapper: dm.* keys) and ensure each is a pair.
Example fix
// before docker run --storage-opt size10G alpine // after docker run --storage-opt size=10G alpine
Defensive patterns
Strategy: validation
Validate before calling
func parseStorageOpt(s string) (string, string, error) {
k, v, ok := strings.Cut(s, "=")
if !ok {
return "", "", errors.New("invalid storage option")
}
return k, v, nil
}
for _, opt := range storageOpts {
if _, _, err := parseStorageOpt(opt); err != nil {
return err
}
} Prevention
- Always write storage options as key=value.
- Shell-quote entire pairs to preserve '='.
- Validate the option set against the storage driver's documented keys before invoking docker.
When it happens
Trigger: `docker run --storage-opt size10G ...` (missing '='), or `--storage-opt nosign`. Any storage option string failing strings.Cut(option, "=") triggers it.
Common situations: Typo omitting '='. Copying a value that lost its '=' through shell quoting/escaping. Using a bare flag name expecting a boolean. Misformatted compose storage_opt map entries passed as a single token.
Related errors
- valid streams are STDIN, STDOUT and STDERR
- you must provide one or more flags when using this command
- cannot attach to a stopped container, start it first
- cannot attach to a paused container, unpause it first
- cannot attach to a restarting container, wait until it is…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/7bee637052e9e7e8.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/opts.go:987
for _, opt := range securityOpts {
if opt == "systempaths=unconfined" {
maskedPaths = []string{}
readonlyPaths = []string{}
} else {
filtered = append(filtered, opt)
}
}
return filtered, maskedPaths, readonlyPaths
}
// parses storage options per container into a map
func parseStorageOpts(storageOpts []string) (map[string]string, error) {
m := make(map[string]string)
for _, option := range storageOpts {
k, v, ok := strings.Cut(option, "=")
if !ok {
return nil, errors.New("invalid storage option")
}
m[k] = v
}
return m, nil
}
// parseDevice parses a device mapping string to a container.DeviceMapping struct
func parseDevice(device, serverOS string) (container.DeviceMapping, error) {
switch serverOS {
case "linux":
return parseLinuxDevice(device)
case "windows":
// Windows doesn't support mapping, so passing the given value as-is.
return container.DeviceMapping{PathOnHost: device}, nil
default:
return container.DeviceMapping{}, fmt.Errorf("unknown server OS: %s", serverOS)
}
}View on GitHub (pinned to 4f84911bfe)