{"record":{"id":"bc47af72b2100095","repo":"argoproj/argo-workflows","slug":"failed-to-re-enter-working-directory-q-after-stag","errorCode":null,"errorMessage":"failed to re-enter working directory %q after staging input artifacts (an input artifact staged at the workingDir path must be a directory): %w","messagePattern":"failed to re-enter working directory %q after staging input artifacts \\(an input artifact staged at the workingDir path must be a directory\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/argoexec/commands/emissary.go","lineNumber":359,"sourceCode":"// into place and re-enters the working directory afterwards, stepping off it\n// for the duration: linking replaces the cwd when an artifact's path is the\n// container's workingDir, Windows refuses to delete a directory in use as a\n// working directory, and a child forked with the deleted directory as cwd\n// would see getcwd() fail and relative paths resolve to nothing. The final\n// chdir follows the symlink to whatever now sits at the path.\nfunc stageInputArtifactsAt(ctx context.Context, baseDir string, tmpl *wfv1.Template) error {\n\torigWd, err := os.Getwd()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read working directory before staging input artifacts: %w\", err)\n\t}\n\tif err := os.Chdir(varRunArgo); err != nil {\n\t\treturn fmt.Errorf(\"failed to leave working directory before staging input artifacts: %w\", err)\n\t}\n\tif err := linkInputArtifactsAt(ctx, baseDir, tmpl); err != nil {\n\t\treturn err\n\t}\n\tif err := os.Chdir(origWd); err != nil {\n\t\treturn fmt.Errorf(\"failed to re-enter working directory %q after staging input artifacts (an input artifact staged at the workingDir path must be a directory): %w\", origWd, err)\n\t}\n\treturn nil\n}\n\n// linkInputArtifactsAt creates a symlink at each input artifact's path\n// pointing to the file that supervisor wrote under /argo/inputs/artifacts/\n// <name>. This replaces the legacy SubPath bind-mount-per-artifact scheme,\n// which can't be used in init-less mode because kubelet pre-creates SubPath\n// entries as empty directories before supervisor can write the real file.\n//\n// Behavior notes for workflow authors: in init-less mode art.Path is a\n// symlink rather than a regular file. `cat`, `open()`, `tar`, `cp`,\n// redirection, etc. all follow symlinks transparently and see identical\n// content. Code that calls `lstat`/`readlink` on art.Path will observe a\n// symlink rather than a regular file. `rm art.Path` removes the symlink\n// only; the underlying artifact stays in the shared emptyDir.\n//\n// Overlapping user volumes are handled by the executor on the write side","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/cmd/argoexec/commands/emissary.go#L341-L377","documentation":"After symlinking input artifacts, argoexec chdirs back to the directory it saved at the start. This error means that restore failed, and the message explains the usual root cause: an input artifact was staged at the template's workingDir path but was a file/symlink rather than a directory, so the original path no longer leads back to a directory.","triggerScenarios":"os.Chdir(origWd) fails after linkInputArtifactsAt ran — typically because the artifact path equals the working directory and the staged entry is a file (symlink) instead of a directory, or the directory was removed during staging.","commonSituations":"Template with workingDir set to the same path as a file-type input artifact; artifact path accidentally nested under the workingDir causing the dir to be replaced; typos where artifact.path == workingDir.","solutions":["Change the input artifact's path so it is a subdirectory of workingDir, not workingDir itself, when the artifact is a file.","Use a directory-type artifact if the working directory must be the artifact root.","Access a file artifact by explicit absolute path in the script instead of relying on cwd.","Fix the workingDir/artifact.path overlap in the template spec and re-run the workflow."],"exampleFix":"// before\nworkingDir: /workspace\ninputs.artifacts: [{name: code, path: /workspace, ...}]  # file artifact replaces cwd\n// after\ninputs.artifacts: [{name: code, path: /workspace/code, ...}]","handlingStrategy":"validation","validationCode":"// Reject templates where a file artifact path collides with workingDir:\nconst bad = tmpl.inputs.artifacts.some(a => a.path === tmpl.workingDir && a.artifactPathIsFile)\nif (bad) throw new Error('file artifact path must not equal workingDir')","typeGuard":null,"tryCatchPattern":"try {\n  await stageArtifacts(tmpl)\n} catch (e) {\n  if (String(e).includes('failed to re-enter working directory')) {\n    // fix artifact.path/workingDir overlap in the template spec\n  }\n}","preventionTips":["Keep artifact paths strictly under workingDir, never equal to it, for file artifacts.","Lint templates for workingDir/artifact.path collisions before submit.","Use directory artifacts if you intend the artifact root to be the working directory."],"tags":["kubernetes","argo-workflows","artifacts","working-directory"],"backgroundTag":"artifact-path-conflict","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"}