argoproj/argo-workflows · error
failed to create directory %s: %w
Error message
failed to create directory %s: %w
What it means
saveArtifact failed to create the parent directory of the artifact destination file under /var/run/argo/outputs/artifacts/ via os.MkdirAll(0o755). The artifact cannot be exported, so the step's output artifact will be missing. The wrapped error reveals the OS cause (usually permissions or disk space).
Source
Thrown at cmd/argoexec/commands/emissary.go:709
func saveArtifact(ctx context.Context, template *wfv1.Template, srcPath string) error {
logger := logging.RequireLoggerFromContext(ctx)
if common.FindOverlappingVolume(template, srcPath) != nil {
logger.WithField("srcPath", srcPath).Info(ctx, "no need to save artifact - on overlapping volume")
return nil
}
if _, err := os.Stat(srcPath); os.IsNotExist(err) { // might be optional, so we ignore
logger.WithField("srcPath", srcPath).WithError(err).Warn(ctx, "cannot save artifact")
return nil
}
dstPath := filepath.Join(varRunArgo, "/outputs/artifacts/", strings.TrimSuffix(srcPath, "/")+".tgz")
logger.WithFields(logging.Fields{
"src": srcPath,
"dst": dstPath,
}).Info(ctx, "saving artifact")
z := filepath.Dir(dstPath)
if err := os.MkdirAll(z, 0o755); err != nil { // chmod rwxr-xr-x
return fmt.Errorf("failed to create directory %s: %w", z, err)
}
dst, err := os.Create(dstPath)
if err != nil {
return fmt.Errorf("failed to create destination %s: %w", dstPath, err)
}
defer func() { _ = dst.Close() }()
if err = archive.TarGzToWriter(ctx, srcPath, gzip.DefaultCompression, dst); err != nil {
return fmt.Errorf("failed to tarball the output %s to %s: %w", srcPath, dstPath, err)
}
if err = dst.Close(); err != nil {
return fmt.Errorf("failed to close %s: %w", dstPath, err)
}
return nil
}
func saveParameter(ctx context.Context, template *wfv1.Template, srcPath string) error {
logger := logging.RequireLoggerFromContext(ctx)
View on GitHub (pinned to 35bff19146)
Solutions
- Read the wrapped error: EEXIST/ENOTDIR means a file occupies a directory component of the artifact path — rename the template's artifact path.
- Free node disk space if ENOSPC.
- Grant the container write access to /var/run/argo (volume mount, correct runAsUser, not read-only).
- Verify the artifact path in the template is a valid directory-form path (path.Dir is computed on it).
Example fix
// before: template artifact path that collides with a file
outputs:
artifacts:
- name: out
path: /tmp/result # /tmp/result is a FILE being both source base and dir component
// after: use a dedicated output directory path
outputs:
artifacts:
- name: out
path: /tmp/results/output.tgz Defensive patterns
Strategy: validation
Validate before calling
// validate template artifact paths before submit
for _, art := range tmpl.Outputs.Artifacts {
if strings.HasSuffix(art.Path, "/") || art.Path == "" {
return fmt.Errorf("artifact %q path %q invalid", art.Name, art.Path)
}
}
// ensure /var/run/argo/outputs is writable in the image
// os.MkdirAll("/var/run/argo/outputs/artifacts", 0o755) Try / catch
if err := runStep(ctx); err != nil {
var wrapped error
if errors.Unwrap(err) != nil {
wrapped = errors.Unwrap(err)
}
if errors.Is(wrapped, os.ErrExist) || errors.Is(wrapped, syscall.ENOTDIR) {
return fixArtifactPathAndResubmit(ctx)
}
return err
} Prevention
- Choose artifact output paths that don't collide with existing files
- Test templates with argo lint and a dry run in a namespace with matching securityContext
- Keep /var/run/argo on a writable emptyDir
- Watch node ENOSPC alerts before large fan-out workflows
When it happens
Trigger: os.MkdirAll(filepath.Dir(dstPath), 0o755) fails while saving an output artifact: /var/run/argo/outputs is not writable, disk is full, or a non-directory file exists at a path component of dstPath (path derived from the template's artifact path).
Common situations: Templates whose output artifact path collides with an existing file (e.g. path /var/run/argo/outputs/artifacts/foo where foo is a file); readOnlyRootFilesystem pods; ENOSPC; runAsUser without write access to /var/run/argo.
Related errors
- failed to create destination %s: %w
- failed to close %s: %w
- failed to stat input artifact %q at %s: %w
- failed to create parent directory for artifact %q at %s: %w
- failed to stat artifact path %q at %s: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/1d5b901a29ffa1d0.
Report an issue: GitHub.