{"record":{"id":"93272f602c651963","repo":"docker/cli","slug":"cannot-mix-bind-options-with-mount-type-s","errorCode":null,"errorMessage":"cannot mix 'bind-*' options with mount type '%s'","messagePattern":"cannot mix 'bind-\\*' options with mount type '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"opts/mount_utils.go","lineNumber":53,"sourceCode":"\t}\n\n\treturn nil\n}\n\n// validateExclusiveOptions checks if the given mount config only contains\n// options for the given mount-type.\n//\n// This is the client-side equivalent of [mounts.validateExclusiveOptions] in\n// the daemon, but with error-messages matching client-side flags / options.\n//\n// [mounts.validateExclusiveOptions]: https://github.com/moby/moby/blob/v2.0.0-beta.6/daemon/volume/mounts/validate.go#L31-L50\nfunc validateExclusiveOptions(m *mount.Mount) error {\n\tif m.Type == \"\" {\n\t\treturn errors.New(\"type is required\")\n\t}\n\n\tif m.Type != mount.TypeBind && m.BindOptions != nil {\n\t\treturn fmt.Errorf(\"cannot mix 'bind-*' options with mount type '%s'\", m.Type)\n\t}\n\tif m.Type != mount.TypeVolume && m.VolumeOptions != nil {\n\t\treturn fmt.Errorf(\"cannot mix 'volume-*' options with mount type '%s'\", m.Type)\n\t}\n\tif m.Type != mount.TypeImage && m.ImageOptions != nil {\n\t\treturn fmt.Errorf(\"cannot mix 'image-*' options with mount type '%s'\", m.Type)\n\t}\n\tif m.Type != mount.TypeTmpfs && m.TmpfsOptions != nil {\n\t\treturn fmt.Errorf(\"cannot mix 'tmpfs-*' options with mount type '%s'\", m.Type)\n\t}\n\tif m.Type != mount.TypeCluster && m.ClusterOptions != nil {\n\t\treturn fmt.Errorf(\"cannot mix 'cluster-*' options with mount type '%s'\", m.Type)\n\t}\n\treturn nil\n}\n\n// parseBoolValue returns the boolean value represented by the string. It returns\n// true if no value is set.","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/opts/mount_utils.go#L35-L71","documentation":"Returned by validateExclusiveOptions (opts/mount_utils.go:53) when a mount's Type is not TypeBind but BindOptions is non-nil. Each mount type owns an exclusive options struct; bind-* options (bind-propagation, bind-recursive, bind-create-src) are only valid for type=bind. The client validates this to produce a friendly error mirroring daemon-side enforcement.","triggerScenarios":"Constructing a mount with type=volume (or tmpfs/image/cluster) while also setting any bind-* option, e.g. `--mount type=volume,source=v,target=/d,bind-propagation=rshared`, or programmatically populating mount.BindOptions on a non-bind Mount.","commonSituations":"Reusing a mount spec template across types, or a UI/compose generator that always emits bind-propagation.","solutions":["Switch the mount type to bind if you need bind-* options.","Or remove all bind-* options (bind-propagation, bind-recursive, bind-create-src) when using type=volume/tmpfs/image/cluster."],"exampleFix":"// before\n--mount \"type=volume,source=v,target=/d,bind-propagation=rshared\"\n\n// after\n--mount \"type=bind,source=/d,target=/d,bind-propagation=rshared\"","handlingStrategy":"validation","validationCode":"func validateExclusive(m mount.Mount) error {\n    if m.Type != mount.TypeBind && m.BindOptions != nil {\n        return fmt.Errorf(\"bind-* options require type=bind, got %s\", m.Type)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := opts.ValidateExclusive(m); err != nil { // if exposed; else call Set and check error\n    return err\n}","preventionTips":["Only attach BindOptions when Type == TypeBind.","In a mount builder, reset the options struct when changing type.","Unit-test that each emitted mount's type matches its options."],"tags":["mount","docker","bind","exclusive-options","validation"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}