argoproj/argo-workflows · error

failed to close temp file: %w

Error message

failed to close temp file: %w

What it means

BufferReaderToTempFile spools an io.Reader into a temp file so artifacts can be saved via SaveStreamViaTempFile. This error wraps a failure from tmpFile.Close() after the stream was successfully written; close can flush buffered data and fail (e.g. ENOSPC), so it is checked explicitly. The temp file is removed and the write is abandoned when this happens.

Source

Thrown at workflow/artifacts/common/streaming.go:47

	noop := func() {}

	tmpFile, err := os.CreateTemp("", pattern)
	if err != nil {
		return "", noop, fmt.Errorf("failed to create temp file: %w", err)
	}
	name := tmpFile.Name()
	cleanup = func() {
		_ = os.Remove(name)
	}

	if _, err := io.Copy(tmpFile, reader); err != nil {
		_ = tmpFile.Close()
		cleanup()
		return "", noop, fmt.Errorf("failed to buffer stream to temp file: %w", err)
	}
	if err := tmpFile.Close(); err != nil {
		cleanup()
		return "", noop, fmt.Errorf("failed to close temp file: %w", err)
	}

	return name, cleanup, nil
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Free disk space on the node / increase the ephemeral storage size for the workflow pod
  2. Check node disk health (dmesg for I/O errors) and move the workflow to a healthy node
  3. Retry the workflow; if it recurs, check kubelet ephemeral-storage limits

Example fix

// before
if err := tmpFile.Close(); err != nil {
	cleanup()
	return "", noop, fmt.Errorf("failed to close temp file: %w", err)
}
// after
// no code fix in caller; fix is infra: ensure the executor's temp volume has free space, e.g.
// spec.volumes: [{name: tmp, emptyDir: {sizeLimit: 1Gi}}] and adequate node disk
Defensive patterns

Strategy: validation

Validate before calling

// before submitting workflows that emit large artifacts, check executor disk space:
// kubectl describe node <node> | grep -A3 'Ephemeral Storage'
// or inside a probe step:
import "syscall"
var st syscall.Statfs_t
_ = syscall.Statfs("/tmp", &st)
freeBytes := st.Bavail * uint64(st.Bsize)
if freeBytes < 512<<20 { /* skip / fail fast */ }

Prevention

When it happens

Trigger: Calling SaveStreamViaTempFile (or BufferReaderToTempFile directly) with a stream whose bytes were written fine to the temp file, but where the final Close() on the temp file fails — typically disk full on the node, an I/O error, or the file having been closed/invalid already.

Common situations: Executor pod running on a node whose emptyDir/tmp volume is full while capturing large script outputs or logs; disk-pressure-evicted nodes; read-only tmp mounts.

Related errors


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