{"record":{"id":"7fa5fdcf264fe0c8","repo":"argoproj/argo-workflows","slug":"failed-to-stat-input-artifact-q-at-s-w","errorCode":null,"errorMessage":"failed to stat input artifact %q at %s: %w","messagePattern":"failed to stat input artifact %q at (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/argoexec/commands/emissary.go","lineNumber":391,"sourceCode":"// 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\n// (supervisor writes to /mainctrfs/<art.Path> instead of /argo/inputs/\n// artifacts/<name>), so no entry appears in the input-artifacts directory\n// and we skip the symlink — main already sees the file at art.Path via\n// its user volume.\nfunc linkInputArtifactsAt(ctx context.Context, baseDir string, tmpl *wfv1.Template) error {\n\tlogger := logging.RequireLoggerFromContext(ctx)\n\tfor _, art := range tmpl.Inputs.Artifacts {\n\t\tsrc := filepath.Join(baseDir, art.Name)\n\t\tif _, statErr := os.Lstat(src); statErr != nil {\n\t\t\tif os.IsNotExist(statErr) {\n\t\t\t\tlogger.WithFields(logging.Fields{\"name\": art.Name, \"path\": art.Path}).Info(ctx, \"no input-artifacts entry (optional or overlap) — skipping symlink\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"failed to stat input artifact %q at %s: %w\", art.Name, src, statErr)\n\t\t}\n\t\tdst := art.Path\n\t\tif dst == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif parent := filepath.Dir(dst); parent != \"\" && parent != \"/\" {\n\t\t\tif err := os.MkdirAll(parent, 0o755); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create parent directory for artifact %q at %s: %w\", art.Name, dst, err)\n\t\t\t}\n\t\t}\n\t\t// If nothing exists at art.Path, just create the symlink. Creating is\n\t\t// always safe — os.Symlink returns EEXIST rather than overwriting and the\n\t\t// MkdirAll above only ever creates — so even when art.Path resolves into a\n\t\t// user volume we deliberately let the artifact land there (the user asked\n\t\t// for it). Only an *overwrite* can destroy data, and that is gated below.\n\t\tif _, err := os.Lstat(dst); err != nil {\n\t\t\tif !os.IsNotExist(err) {\n\t\t\t\treturn fmt.Errorf(\"failed to stat artifact path %q at %s: %w\", art.Name, dst, err)","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/cmd/argoexec/commands/emissary.go#L373-L409","documentation":"For each input artifact, linkInputArtifactsAt Lstats the supervisor-written source at <baseDir>/<artifact-name> before symlinking it to the artifact's declared path. Missing sources are treated as optional and skipped, but any other stat error (EACCES, ELOOP, EIO) is fatal and wrapped as this error. It means the executor could not even inspect the staged artifact entry.","triggerScenarios":"os.Lstat(src) fails with a non-ENOsport error: /argo/inputs/artifacts (or the configured baseDir) is not readable, the filesystem returned I/O error, or too many symlink levels (ELOOP) from a corrupted emptyDir.","commonSituations":"Pod security contexts denying read on /argo; corrupted node disk/emptyDir; node under disk pressure causing I/O errors; a user-supplied baseDir override pointing somewhere inaccessible in tests.","solutions":["Read the wrapped inner error to distinguish EACCES (permissions) from EIO (disk).","Fix the executor container's securityContext so /var/run/argo is readable/writable.","Check the node's disk health and events (kubectl describe node) for I/O pressure.","If the artifact genuinely wasn't staged, verify the init/supervisor artifact-staging logs — a missing entry would normally be skipped, so a persistent stat error implies filesystem trouble.","Resubmit the workflow on a different node to rule out node-local disk corruption."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Verify the staged artifact source is reachable before linking:\ntest -e /argo/inputs/artifacts/<name> || echo \"not staged (optional?)\"","typeGuard":null,"tryCatchPattern":"try {\n  await stageArtifacts(tmpl)\n} catch (e) {\n  if (String(e).includes('failed to stat input artifact')) {\n    if (isTransient(e)) await retryWithBackoff(stageArtifacts) // e.g. NFS EIO\n    else throw e // permissions/filesystem corruption need a fix\n  }\n}","preventionTips":["Grant the executor user read access to /var/run/argo and its children.","Monitor node disk health; resubmit on another node after EIO.","Check init/supervisor logs when artifacts seem unstaged."],"tags":["kubernetes","argo-workflows","artifacts","filesystem"],"backgroundTag":"stat-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"}