{"record":{"id":"9b353896674fb42f","repo":"argoproj/argo-workflows","slug":"unable-to-remove-attempted-file-download-s-w","errorCode":null,"errorMessage":"unable to remove attempted file download %s: %w","messagePattern":"unable to remove attempted file download (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/azure/azure.go","lineNumber":159,"sourceCode":"\t} else if !bloberror.HasCode(origErr, bloberror.BlobNotFound) {\n\t\treturn fmt.Errorf(\"unable to download blob %s: %w\", artifact.Azure.Blob, origErr)\n\t}\n\n\tisDir, err := azblobDriver.IsDirectory(ctx, artifact)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to determine if %s is a directory: %w\", artifact.Azure.Blob, err)\n\t}\n\n\t// It's not a directory and the file doesn't exist, Return the original NoSuchKey error.\n\tif !isDir && !isEmptyFile {\n\t\treturn argoerrors.New(argoerrors.CodeNotFound, origErr.Error())\n\t}\n\n\t// When we tried to download the blob as a file, we created an empty file for the\n\t// blob as a target. We need to delete that empty file so we can re-create as a directory.\n\terr = os.Remove(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to remove attempted file download %s: %w\", path, err)\n\t}\n\n\t// It's a directory, so download all of the files.\n\terr = azblobDriver.DownloadDirectory(ctx, containerClient, artifact, path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to download directory %s: %w\", artifact.Azure.Blob, err)\n\t}\n\n\treturn nil\n}\n\n// DownloadFile downloads a single file from Azure Blob Storage\nfunc DownloadFile(ctx context.Context, containerClient *container.Client, blobName, path string) error {\n\tblobClient := containerClient.NewBlobClient(blobName)\n\n\terr := os.MkdirAll(filepath.Dir(path), 0755)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create dir for file %s: %w\", path, err)","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/azure/azure.go#L141-L177","documentation":"Load determined the blob key is actually a directory prefix. It previously created a local placeholder file at `path` while attempting a file download, and now must os.Remove it before re-creating the location as a directory. This error means the local filesystem refused the remove (permission, path is a non-empty dir, mount issues).","triggerScenarios":"os.Remove(path) fails because path is a non-empty directory (ADLS Gen2 downloaded a real directory with contents), the volume is read-only, the file is owned by another user, or path points at a protected mount point (e.g. artifact destination = a mounted volume root).","commonSituations":"Output/input artifact path set to an existing non-empty directory in the container, emptyDir mounted read-only, running argoexec as non-root while a prior step created the file as root.","solutions":["Point the artifact path at a fresh, dedicated directory (e.g. /mnt/out) that does not already contain content.","Ensure the volume backing the path is writable by the executor user (not read-only).","If the path exists as a non-empty dir from a previous step, use a unique path per step or clean it before.","Run the pod/executor with sufficient permissions (securityContext) to delete the placeholder file.","Check the wrapped os error: EACCES => permissions, EBUSY/EXDEV => mount layout, ENOTEMPTY => existing content."],"exampleFix":"// before: artifact path collides with existing dir\npath: /mnt/src\n// after: dedicated writable output dir\npath: /mnt/out/artifacts","handlingStrategy":"validation","validationCode":"st, err := os.Lstat(path)\nif err == nil && st.IsDir() {\n\t// destination occupied by a directory; clean or pick another path\n\tif err := os.RemoveAll(path); err != nil { return err }\n}\nif err := unix.Access(filepath.Dir(path), unix.W_OK); err != nil { return err }","typeGuard":"func writableArtifactPath(p string) error {\n\tif fi, err := os.Lstat(p); err == nil && fi.IsDir() {\n\t\treturn fmt.Errorf(\"path %s is an existing directory\", p)\n\t}\n\treturn nil\n}","tryCatchPattern":null,"preventionTips":["Use a fresh dedicated artifact directory (e.g. /mnt/out) per step","Never point artifacts at read-only or shared mount roots","Set matching fsGroup/runAsUser in securityContext for the executor","Clean step output paths before downloads in the entrypoint script"],"tags":["filesystem","azure","artifacts","permissions"],"backgroundTag":"local-file-remove-failed","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"}