docker/cli · error
cannot mix 'cluster-*' options with mount type
Error message
cannot mix 'cluster-*' options with mount type '%s'
What it means
Returned by validateExclusiveOptions (opts/mount_utils.go:65) when a mount's Type is not TypeCluster but ClusterOptions is non-nil. The cluster-* options are exclusive to type=cluster mounts.
Solutions
- Use type=cluster when you need cluster-* options.
- Or remove cluster options from non-cluster mounts.
Example fix
// before
mount := mount.Mount{Type: mount.TypeVolume, ClusterOptions: &mount.ClusterOptions{}}
// after
mount := mount.Mount{Type: mount.TypeCluster, ClusterOptions: &mount.ClusterOptions{}} Defensive patterns
Strategy: validation
Validate before calling
func validateExclusive(m mount.Mount) error {
if m.Type != mount.TypeCluster && m.ClusterOptions != nil {
return fmt.Errorf("cluster-* options require type=cluster, got %s", m.Type)
}
return nil
} Try / catch
if err := m.Set(spec); err != nil {
return fmt.Errorf("mount %q: %w", spec, err)
} Prevention
- Only attach ClusterOptions when Type == TypeCluster.
- Keep cluster-mount construction separate from standalone mounts.
- Test swarm mount specs for correct type/options pairing.
When it happens
Trigger: Setting cluster options on a bind/volume/tmpfs/image mount, or programmatically setting mount.ClusterOptions on a Mount whose Type isn't TypeCluster. This is the swarm/cluster-mount variant of the other exclusive-option checks.
Common situations: Using cluster-mount options in a standalone container context, or a generator emitting ClusterOptions unconditionally.
Related errors
- cannot mix 'bind-*' options with mount type
- cannot mix 'volume-*' options with mount type
- cannot mix 'image-*' options with mount type
- cannot mix 'tmpfs-*' options with mount type
- invalid value for ' ': value is empty
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/19f0ac9810a1fa7a.
Report an issue: GitHub.
Appendix: source
Thrown at opts/mount_utils.go:65
func validateExclusiveOptions(m *mount.Mount) error {
if m.Type == "" {
return errors.New("type is required")
}
if m.Type != mount.TypeBind && m.BindOptions != nil {
return fmt.Errorf("cannot mix 'bind-*' options with mount type '%s'", m.Type)
}
if m.Type != mount.TypeVolume && m.VolumeOptions != nil {
return fmt.Errorf("cannot mix 'volume-*' options with mount type '%s'", m.Type)
}
if m.Type != mount.TypeImage && m.ImageOptions != nil {
return fmt.Errorf("cannot mix 'image-*' options with mount type '%s'", m.Type)
}
if m.Type != mount.TypeTmpfs && m.TmpfsOptions != nil {
return fmt.Errorf("cannot mix 'tmpfs-*' options with mount type '%s'", m.Type)
}
if m.Type != mount.TypeCluster && m.ClusterOptions != nil {
return fmt.Errorf("cannot mix 'cluster-*' options with mount type '%s'", m.Type)
}
return nil
}
// parseBoolValue returns the boolean value represented by the string. It returns
// true if no value is set.
//
// It is similar to [strconv.ParseBool], but only accepts 1, true, 0, false.
// Any other value returns an error.
func parseBoolValue(key string, val string, hasValue bool) (bool, error) {
if !hasValue {
return true, nil
}
switch val {
case "1", "true":
return true, nil
case "0", "false":
return false, nilView on GitHub (pinned to 4f84911bfe)