argoproj/argo-workflows · error

volumeMounts[%d].mountPath '%s' already mounted in %s

Error message

volumeMounts[%d].mountPath '%s' already mounted in %s

What it means

Within a ContainerSetTemplate all containers share the pod's filesystem, so two volumeMounts may not claim the same mountPath. Validate() tracks every mountPath in a map and fails when a later mount collides with an earlier one, reporting which index/path was already mounted and where.

Source

Thrown at pkg/apis/workflow/v1alpha1/container_set_template_types.go:108

func (in *ContainerSetTemplate) Validate() error {
	if len(in.Containers) == 0 {
		return fmt.Errorf("containers must have at least one container")
	}

	names := make([]string, 0)
	for _, ctr := range in.Containers {
		names = append(names, ctr.Name)
	}
	err := validateWorkflowFieldNames(names, false)
	if err != nil {
		return fmt.Errorf("containers%s", err.Error())
	}

	// Ensure there are no collisions with volume mountPaths and artifact load paths
	mountPaths := make(map[string]string)
	for i, volMount := range in.VolumeMounts {
		if prev, ok := mountPaths[volMount.MountPath]; ok {
			return fmt.Errorf("volumeMounts[%d].mountPath '%s' already mounted in %s", i, volMount.MountPath, prev)
		}
		mountPaths[volMount.MountPath] = fmt.Sprintf("volumeMounts.%s", volMount.Name)
	}

	// Ensure the dependencies are defined
	nameToContainer := make(map[string]ContainerNode)
	for _, ctr := range in.Containers {
		nameToContainer[ctr.Name] = ctr
	}
	for _, ctr := range in.Containers {
		for _, depName := range ctr.Dependencies {
			_, ok := nameToContainer[depName]
			if !ok {
				return fmt.Errorf("containers.%s dependency '%s' not defined", ctr.Name, depName)
			}
		}
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Change one volumeMount's mountPath to a distinct directory (e.g. /data vs /data2), or use different subPath values.
  2. Remove the redundant volumeMount if both entries reference the same volume/path.
  3. Review the error's "already mounted in" suffix to find the original volumeMount.name and reconcile the two.

Example fix

// before
containerSet:
  volumeMounts:
    - name: workdir
      mountPath: /data
    - name: cache
      mountPath: /data
// after
containerSet:
  volumeMounts:
    - name: workdir
      mountPath: /data
    - name: cache
      mountPath: /cache
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]string{}
for i, vm := range cs.ContainerSet.VolumeMounts {
    if prev, ok := seen[vm.MountPath]; ok {
        return fmt.Errorf("mountPath %q duplicated (%s vs %s)", vm.MountPath, prev, vm.Name)
    }
    seen[vm.MountPath] = vm.Name
}

Try / catch

if err := cs.Validate(); err != nil {
    if strings.Contains(err.Error(), "already mounted in") {
        // parse the conflicting index/path from the message and dedupe mounts
    }
    return err
}

Prevention

When it happens

Trigger: Two containerSet.volumeMounts entries (or two containers mounting the same volume at the same subPath/mountPath) specify the identical mountPath string in the same container set.

Common situations: Copying a volumeMount block and forgetting to change mountPath; mounting the same shared volume at the same path in two containers (in a containerSet the mounts are validated set-wide, unlike a normal pod); generated manifests merging mounts from multiple sources.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/54211b0137bdc4d7. Report an issue: GitHub.