argoproj/argo-workflows · error

failed to write template: %w

Error message

failed to write template: %w

What it means

runSupervisorPreMain (the testable core of the supervisor's pre-main phase) calls the WriteTemplate stage first; if it fails the error is wrapped as "failed to write template". WriteTemplate persists the workflow template to /var/run/argo/template so the main container can read it, so failure means the supervisor could not set up the contract shared with the main container and pre-main short-circuits.

Source

Thrown at cmd/argoexec/commands/supervisor.go:144

// supervisorPreMain runs the pre-main phase: template write, script staging,
// and input artifact download (non-plugin and per-plugin in parallel).
func supervisorPreMain(ctx context.Context, wfExecutor *wfexecutor.WorkflowExecutor) error {
	// Zero umask so files/dirs created here are accessible to main when it
	// runs as a different uid. The legacy init container does the same.
	osspecific.AllowGrantingAccessToEveryone()

	// A stale marker from a prior attempt needs no explicit cleanup: the
	// heartbeat's initial RUNNING write (startStatusHeartbeat, before we get
	// here) has already overwritten it with a fresh mtime.
	return runSupervisorPreMain(ctx, wfExecutor, inputArtifactPluginNames())
}

// runSupervisorPreMain is the testable core of supervisorPreMain. Takes
// the plugin name list explicitly so tests don't have to mutate env vars.
func runSupervisorPreMain(ctx context.Context, stages preMainStages, pluginNames []wfv1.ArtifactPluginName) error {
	if err := stages.WriteTemplate(); err != nil {
		return fmt.Errorf("failed to write template: %w", err)
	}
	if err := stages.StageFiles(ctx); err != nil {
		return fmt.Errorf("failed to stage files: %w", err)
	}

	g, gctx := errgroup.WithContext(ctx)
	g.Go(func() error {
		if err := stages.LoadArtifactsWithoutPlugins(gctx); err != nil {
			return fmt.Errorf("failed to load non-plugin input artifacts: %w", err)
		}
		return nil
	})
	for _, name := range pluginNames {
		g.Go(func() error {
			if err := stages.LoadArtifactsFromPlugin(gctx, name); err != nil {
				return fmt.Errorf("failed to load input artifacts from plugin %q: %w", name, err)
			}
			return nil

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped cause for the underlying filesystem error (EACCES/ENOSPC/ENOENT)
  2. Ensure /var/run/argo exists and is writable by the argoexec user in the pod
  3. Verify the shared volume is defined for both supervisor and main containers
  4. Check node DiskPressure conditions and pod ephemeral-storage limits

Example fix

// before: no volume mount in the pod spec
templates:
  - name: main
    container: ...
// after: ensure the shared argo volume is mounted
spec:
  volumes:
    - name: var-run-argo
      emptyDir: {}
  containers:
    - name: main
      volumeMounts:
        - name: var-run-argo
          mountPath: /var/run/argo
Defensive patterns

Strategy: try-catch

Validate before calling

// inside the pod, before main runs:
// test -w /var/run/argo && df -h /var/run/argo

Try / catch

if err := stages.WriteTemplate(); err != nil {
    return fmt.Errorf("failed to write template: %w", err) // inspect cause for fs errors
}
// caller: errors.Is(err, syscall.ENOSPC) / errors.As(err, *fs.PathError)

Prevention

When it happens

Trigger: supervisorPreMain → runSupervisorPreMain where the WriteTemplate stage returns an error — unwritable /var/run/argo, disk full, or marshaling problems with the template payload.

Common situations: Missing or read-only shared volume mount at /var/run/argo in init-less workflow pods; ephemeral storage exhausted; SELinux/AppArmor blocking writes to the emptyDir.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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