docker/cli · error
invalid value for : (must be "enabled", "disabled"…
Error message
invalid value for %s: %s (must be "enabled", "disabled", "writable", or "readonly")
What it means
Returned by MountOpt.Set (opts/mount.go:103) when the `bind-recursive` option receives a value other than the four allowed: enabled, disabled, writable, readonly. Each maps to a distinct recursive-bind behavior (full recursion, no recursion, writable-non-recursive, force-recursive-read-only), so an unknown value cannot be mapped.
Solutions
- Use one of the exact lowercase values: enabled, disabled, writable, readonly.
- For the old bind-nonrecursive=true behavior, use bind-recursive=disabled.
- Remember readonly/writable variants additionally require the readonly option (validated later in validateMountOptions).
Example fix
// before --mount "type=bind,source=/data,target=/data,bind-recursive=true" // after --mount "type=bind,source=/data,target=/data,readonly,bind-recursive=readonly"
Defensive patterns
Strategy: validation
Validate before calling
var bindRecursiveValues = map[string]bool{"enabled": true, "disabled": true, "writable": true, "readonly": true}
func validateBindRecursive(v string) error {
if !bindRecursiveValues[v] {
return fmt.Errorf("bind-recursive must be one of enabled, disabled, writable, readonly; got %q", v)
}
return nil
} Try / catch
if err := m.Set(spec); err != nil {
return fmt.Errorf("mount %q: %w", spec, err)
} Prevention
- Use the exact lowercase vocabulary; values are case-sensitive.
- Remember readonly/writable also require the readonly option.
- Migrate bind-nonrecursive=true to bind-recursive=disabled.
When it happens
Trigger: Passing `bind-recursive=true`, `bind-recursive=yes`, `bind-recursive=1`, or any typo'd/uppercase variant (note values are not lowercased, so `Enabled` also fails).
Common situations: Migrating from the deprecated `bind-nonrecursive` and guessing the replacement's vocabulary, using boolean-style values, or case mismatch.
Related errors
- cannot mix 'bind-*' options with mount type
- bind options are incompatible with type volume
- bind options are incompatible with type image
- option 'bind-recursive=writable' requires 'readonly' to be…
- option 'bind-recursive=readonly' requires 'readonly' to be…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/0bb9c5ab7c2229f7.
Report an issue: GitHub.
Appendix: source
Thrown at opts/mount.go:103
mount.Consistency = mounttypes.Consistency(strings.ToLower(val))
case "bind-propagation":
ensureBindOptions(&mount).Propagation = mounttypes.Propagation(strings.ToLower(val))
case "bind-nonrecursive":
return errors.New("bind-nonrecursive is deprecated, use bind-recursive=disabled instead")
case "bind-recursive":
switch val {
case "enabled": // read-only mounts are recursively read-only if Engine >= v25 && kernel >= v5.12, otherwise writable
// NOP
case "disabled": // previously "bind-nonrecursive=true"
ensureBindOptions(&mount).NonRecursive = true
case "writable": // conforms to the default read-only bind-mount of Docker v24; read-only mounts are recursively mounted but not recursively read-only
ensureBindOptions(&mount).ReadOnlyNonRecursive = true
case "readonly": // force recursively read-only, or raise an error
ensureBindOptions(&mount).ReadOnlyForceRecursive = true
// TODO: implicitly set propagation and error if the user specifies a propagation in a future refactor/UX polish pass
// https://github.com/docker/cli/pull/4316#discussion_r1341974730
default:
return fmt.Errorf(`invalid value for %s: %s (must be "enabled", "disabled", "writable", or "readonly")`, key, val)
}
case "bind-create-src":
ensureBindOptions(&mount).CreateMountpoint, err = parseBoolValue(key, val, hasValue)
if err != nil {
return err
}
case "volume-subpath":
ensureVolumeOptions(&mount).Subpath = val
case "volume-nocopy":
ensureVolumeOptions(&mount).NoCopy, err = parseBoolValue(key, val, hasValue)
if err != nil {
return err
}
case "volume-label":
volumeOpts := ensureVolumeOptions(&mount)
volumeOpts.Labels = setValueOnMap(volumeOpts.Labels, val)
case "volume-driver":
ensureVolumeDriver(&mount).Name = valView on GitHub (pinned to 4f84911bfe)