{"record":{"id":"2d31a24d849da5f3","repo":"argoproj/argo-workflows","slug":"failed-to-clear-existing-path-for-artifact-q-at","errorCode":null,"errorMessage":"failed to clear existing path for artifact %q at %s: %w","messagePattern":"failed to clear existing path for artifact %q at (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/argoexec/commands/emissary.go","lineNumber":434,"sourceCode":"\t\t\t// (resolve the parent, not the final element, so an image symlink *at*\n\t\t\t// art.Path is just unlinked rather than followed). If that resolved\n\t\t\t// path overlaps a user-declared volume, clearing it would recurse into\n\t\t\t// and destroy a live PVC/hostPath/emptyDir, so refuse. Benign system\n\t\t\t// mounts (tmpfs /run, the overlay rootfs) are not declared user volumes\n\t\t\t// and so remain safe to shadow.\n\t\t\trealParent, evalErr := filepath.EvalSymlinks(filepath.Dir(dst))\n\t\t\tif evalErr != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to resolve parent of artifact path %q at %s: %w\", art.Name, dst, evalErr)\n\t\t\t}\n\t\t\tresolved := filepath.Join(realParent, filepath.Base(dst))\n\t\t\tif mnt := common.FindOverlappingVolume(tmpl, resolved); mnt != nil {\n\t\t\t\treturn 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)\n\t\t\t}\n\t\t\tif mnt := common.FindVolumeMountNestedUnderPath(tmpl, resolved); mnt != nil {\n\t\t\t\treturn 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)\n\t\t\t}\n\t\t\tif rmErr := os.RemoveAll(dst); rmErr != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to clear existing path for artifact %q at %s: %w\", art.Name, dst, rmErr)\n\t\t\t}\n\t\t}\n\t\tif err := os.Symlink(src, dst); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to symlink input artifact %q (%s -> %s): %w\", art.Name, dst, src, err)\n\t\t}\n\t\tlogger.WithFields(logging.Fields{\"name\": art.Name, \"src\": src, \"dst\": dst}).Debug(ctx, \"linked input artifact\")\n\t}\n\treturn nil\n}\n\n// waitForSupervisorReady blocks until the supervisor's status marker reports a\n// terminal outcome (READY/FAILED), or until the supervisor is presumed dead.\n// Used only in init-less pod mode where main and supervisor start concurrently.\n// VarRunArgoPath itself is guaranteed to exist because the emissary has\n// already created /var/run/argo/ctr/<name> earlier in main, which MkdirAll'd\n// the full parent chain.\nfunc waitForSupervisorReady(ctx context.Context) error {\n\treturn waitForSupervisorReadyAt(ctx, common.StatusMarkerPath, supervisorHeartbeatTimeout, supervisorStatusPollInterval)","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/cmd/argoexec/commands/emissary.go#L416-L452","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the destination path writable by the container user (chown/chmod in the image, or run with an appropriate securityContext fsGroup)","Choose a destination on a writable filesystem (emptyDir volume, /tmp)","If the path is a mount point, change the artifact path so it is not exactly at a mountPath","Ensure the container filesystem is not mounted readOnly for the directory containing the path"],"exampleFix":"# before\nsecurityContext:\n  runAsUser: 1000\ninputs:\n  artifacts:\n  - name: cfg\n    path: /etc/app/config.yaml      # root-owned, non-root cannot clear\n# after\ninputs:\n  artifacts:\n  - name: cfg\n    path: /tmp/app/config.yaml","handlingStrategy":"validation","validationCode":"// In the image build, pre-create and chown the artifact destination directory:\n# Dockerfile\nRUN mkdir -p /etc/app && chown 1000:1000 /etc/app\n# Or choose a path on an emptyDir volume, which is always writable by the container user.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-create artifact destination directories in the image with correct ownership","Run containers with securityContext.fsGroup matching the volume GID","Avoid read-only root filesystems when using artifact paths on /","Never place artifact paths exactly at mountPath locations"],"tags":["kubernetes","argo-workflows","artifacts","permissions","filesystem"],"backgroundTag":"filesystem-permission-denied","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}