argoproj/argo-workflows · error

failed to clear existing path for artifact %q at %s: %w

Error message

failed to clear existing path for artifact %q at %s: %w

What it means

After the volume-safety checks pass, argoexec removes whatever already exists at the artifact destination (os.RemoveAll) so the symlink can be placed. If that removal fails (permissions, read-only filesystem, EBUSY), the error is wrapped with this message and the step fails.

Source

Thrown at cmd/argoexec/commands/emissary.go:434

			// (resolve the parent, not the final element, so an image symlink *at*
			// art.Path is just unlinked rather than followed). If that resolved
			// path overlaps a user-declared volume, clearing it would recurse into
			// and destroy a live PVC/hostPath/emptyDir, so refuse. Benign system
			// mounts (tmpfs /run, the overlay rootfs) are not declared user volumes
			// and so remain safe to shadow.
			realParent, evalErr := filepath.EvalSymlinks(filepath.Dir(dst))
			if evalErr != nil {
				return fmt.Errorf("failed to resolve parent of artifact path %q at %s: %w", art.Name, dst, evalErr)
			}
			resolved := filepath.Join(realParent, filepath.Base(dst))
			if mnt := common.FindOverlappingVolume(tmpl, resolved); mnt != nil {
				return fmt.Errorf("refusing to stage input artifact %q at %s: it resolves to %s inside volume mount %q (%s), and clearing it would destroy the mounted volume; change the artifact path or volume mount so they do not overlap", art.Name, dst, resolved, mnt.Name, mnt.MountPath)
			}
			if mnt := common.FindVolumeMountNestedUnderPath(tmpl, resolved); mnt != nil {
				return fmt.Errorf("refusing to stage input artifact %q at %s: it resolves to %s which contains volume mount %q (%s), and clearing it would destroy the mounted volume; change the artifact path or volume mount so they do not overlap", art.Name, dst, resolved, mnt.Name, mnt.MountPath)
			}
			if rmErr := os.RemoveAll(dst); rmErr != nil {
				return fmt.Errorf("failed to clear existing path for artifact %q at %s: %w", art.Name, dst, rmErr)
			}
		}
		if err := os.Symlink(src, dst); err != nil {
			return fmt.Errorf("failed to symlink input artifact %q (%s -> %s): %w", art.Name, dst, src, err)
		}
		logger.WithFields(logging.Fields{"name": art.Name, "src": src, "dst": dst}).Debug(ctx, "linked input artifact")
	}
	return nil
}

// waitForSupervisorReady blocks until the supervisor's status marker reports a
// terminal outcome (READY/FAILED), or until the supervisor is presumed dead.
// Used only in init-less pod mode where main and supervisor start concurrently.
// VarRunArgoPath itself is guaranteed to exist because the emissary has
// already created /var/run/argo/ctr/<name> earlier in main, which MkdirAll'd
// the full parent chain.
func waitForSupervisorReady(ctx context.Context) error {
	return waitForSupervisorReadyAt(ctx, common.StatusMarkerPath, supervisorHeartbeatTimeout, supervisorStatusPollInterval)

View on GitHub (pinned to 35bff19146)

Solutions

  1. Make the destination path writable by the container user (chown/chmod in the image, or run with an appropriate securityContext fsGroup)
  2. Choose a destination on a writable filesystem (emptyDir volume, /tmp)
  3. If the path is a mount point, change the artifact path so it is not exactly at a mountPath
  4. Ensure the container filesystem is not mounted readOnly for the directory containing the path

Example fix

# before
securityContext:
  runAsUser: 1000
inputs:
  artifacts:
  - name: cfg
    path: /etc/app/config.yaml      # root-owned, non-root cannot clear
# after
inputs:
  artifacts:
  - name: cfg
    path: /tmp/app/config.yaml
Defensive patterns

Strategy: validation

Validate before calling

// In the image build, pre-create and chown the artifact destination directory:
# Dockerfile
RUN mkdir -p /etc/app && chown 1000:1000 /etc/app
# Or choose a path on an emptyDir volume, which is always writable by the container user.

Prevention

When it happens

Trigger: os.RemoveAll(dst) returns an error while staging input artifacts: destination is on a read-only filesystem, owned by another user, a non-empty mount point, or otherwise undeletable.

Common situations: Artifact path on a read-only rootfs or read-only PVC; destination is an active mount point (busy); container runs as non-root but path is owned by root; image sets immutable attributes.

Related errors


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