argoproj/argo-workflows · error

failed to create artifact temporary parent directory %s: %w

Error message

failed to create artifact temporary parent directory %s: %w

What it means

Before loading an artifact, the executor stages it at <artPath>.tmp and ensures the temporary file's parent directory exists via os.MkdirAll(tempArtDir, 0o700). If that OS call fails, this error wraps the underlying filesystem error.

Source

Thrown at workflow/executor/executor.go:328

		artPath = path.Join(common.ExecutorArtifactBaseDir, art.Name)
	} else {
		// If we get here, it means the input artifact path overlaps with a user-specified
		// volumeMount in the container. Because we also implement input artifacts as volume
		// mounts, we need to load the artifact into the user specified volume mount,
		// as opposed to the `input-artifacts` volume that is an implementation detail
		// unbeknownst to the user.
		logger.WithFields(logging.Fields{"path": art.Path, "mountPath": mnt.MountPath}).Info(ctx, "Specified artifact path overlaps with volume mount, extracting to volume mount")
		artPath = path.Join(common.ExecutorMainFilesystemDir, art.Path)
	}

	// The artifact is downloaded to a temporary location, after which we determine if
	// the file is a tarball or not. If it is, it is first extracted then renamed to
	// the desired location. If not, it is simply renamed to the location.
	tempArtPath := artPath + ".tmp"
	// Ensure parent directory exist, create if missing
	tempArtDir := filepath.Dir(tempArtPath)
	if mkdirErr := os.MkdirAll(tempArtDir, 0o700); mkdirErr != nil {
		return fmt.Errorf("failed to create artifact temporary parent directory %s: %w", tempArtDir, mkdirErr)
	}
	ctx, span := we.Tracing.StartLoadArtifact(ctx, artPath)
	defer span.End()
	err = artDriver.Load(ctx, driverArt, tempArtPath)
	if err != nil {
		if art.Optional && argoerrs.IsCode(argoerrs.CodeNotFound, err) {
			logger.WithField("name", art.Name).Info(ctx, "Skipping optional input artifact that was not found")
			return nil
		}
		return fmt.Errorf("artifact %s failed to load: %w", art.Name, err)
	}

	err = we.unarchiveArtifact(ctx, art, tempArtPath, artPath)
	if err != nil {
		return err
	}

	logger.WithField("path", artPath).Info(ctx, "Successfully download file")

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped mkdirErr in the message for the exact OS reason (EACCES, EROFS, ENOTDIR)
  2. Make the artifact's parent directory a writable volume (emptyDir or writable PVC) and run the container as a user with write access
  3. Ensure the artifact path's parent is not a mounted file (a single-file ConfigMap mount blocks directory creation)
  4. Pick a writable mountPath (e.g. /mnt/data) for the input artifact

Example fix

# before
artifacts:
  - name: data
    path: /etc/config/data.tar.gz   # read-only single-file mount
# after
artifacts:
  - name: data
    path: /mnt/work/data.tar.gz     # writable emptyDir mounted at /mnt/work
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the artifact path parent is writable before running the pod:
// kubectl exec <pod> -- ls -ld /mnt/work   # check ownership and writability
// Prefer dedicated writable volumes for artifact paths

Try / catch

if err := loadArtifacts(ctx); err != nil {
	var perr *fs.PathError
	if errors.As(err, &perr) && perr.Op == "mkdir" {
		// fix volume permissions/mount type, then retry
	}
}

Prevention

When it happens

Trigger: os.MkdirAll cannot create filepath.Dir(artPath + '.tmp') — e.g. the container filesystem is read-only, the mountpoint is not writable by the executor user, a component of the path is a file, or disk/quota issues prevent directory creation.

Common situations: Input artifact path inside a read-only volume or under /proc//etc; volume mounted root-owned with the pod running non-root; artifact path configured as a file (e.g. mounting a single-file ConfigMap) so a directory can't be created along that path.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/d49b7316ac4aa652. Report an issue: GitHub.