docker/cli · error
duplicate mount target
Error message
duplicate mount target
What it means
Thrown by updateMounts (cli/command/service/update.go:934) while indexing newly-added mounts by their Target path. If two `--mount-add` flags specify the same container destination, the second collides in the mountsByTarget map and the error fires, since a container cannot have two mounts bound to one path.
Solutions
- Give each mount a distinct target path.
- If the intent is to replace an existing mount, remove the old one first with `--mount-rm <target>` then add the new source for the same target.
- Dedupe the mount list by target before issuing the update.
Example fix
// before docker service update \ --mount-add type=bind,src=/a,target=/data \ --mount-add type=volume,src=vol,target=/data web // after docker service update \ --mount-add type=bind,src=/a,target=/data \ --mount-add type=volume,src=vol,target=/cache web
Defensive patterns
Strategy: validation
Validate before calling
// Dedupe mount targets before building the --mount-add list.
seen := map[string]struct{}{}
for _, m := range mounts {
if _, dup := seen[m.Target]; dup {
return fmt.Errorf("duplicate mount target %q", m.Target)
}
seen[m.Target] = struct{}{}
} Prevention
- Key every mount list by target path when rendering from templates.
- When replacing a mount, pair --mount-rm <target> with --mount-add rather than double-adding.
- Lint Compose/spec files for duplicate volume destinations.
When it happens
Trigger: Passing multiple `--mount-add` with an identical `target=`/`dst=`, e.g. `docker service update --mount-add type=bind,src=/a,target=/data --mount-add type=volume,src=vol,target=/data <svc>`.
Common situations: Copy-pasting a mount flag and editing only the source while leaving the target; templating that renders the same target twice; refactoring a volume list and forgetting to dedupe destinations.
Related errors
- other flags may not be combined with --rollback
- placement preference must be of the format
- replicas can only be used with replicated or replicated-job…
- replicas-max-per-node can only be used with replicated or…
- max-concurrent can only be used with replicated-job mode
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/02ce7b85b0ecd720.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/service/update.go:934
keyFunc func(string) string,
) []string {
newSeq := []string{}
for _, item := range seq {
if _, exists := toRemove[keyFunc(item)]; !exists {
newSeq = append(newSeq, item)
}
}
return newSeq
}
func updateMounts(flags *pflag.FlagSet, mounts *[]mount.Mount) error {
mountsByTarget := map[string]mount.Mount{}
if flags.Changed(flagMountAdd) {
values := flags.Lookup(flagMountAdd).Value.(*opts.MountOpt).Value()
for _, mnt := range values {
if _, ok := mountsByTarget[mnt.Target]; ok {
return errors.New("duplicate mount target")
}
mountsByTarget[mnt.Target] = mnt
}
}
// Add old list of mount points minus updated one.
for _, mnt := range *mounts {
if _, ok := mountsByTarget[mnt.Target]; !ok {
mountsByTarget[mnt.Target] = mnt
}
}
newMounts := make([]mount.Mount, 0, len(mountsByTarget))
toRemove := buildToRemoveSet(flags, flagMountRemove)
for _, mnt := range mountsByTarget {
if _, exists := toRemove[mnt.Target]; !exists {View on GitHub (pinned to 4f84911bfe)