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 nilView on GitHub (pinned to 35bff19146)
Solutions
- Check the wrapped cause for the underlying filesystem error (EACCES/ENOSPC/ENOENT)
- Ensure /var/run/argo exists and is writable by the argoexec user in the pod
- Verify the shared volume is defined for both supervisor and main containers
- 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
- Always mount an emptyDir at /var/run/argo shared by supervisor and main
- Set fsGroup/securityContext so argoexec can write the mount
- Monitor ephemeral storage on nodes running workflows
- Keep a smoke-test workflow exercising the init-less path in CI
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
- failed to stage files: %w
- failed to write initial status marker: %w
- %w
- failed to load non-plugin input artifacts: %w
- failed to load input artifacts from plugin %q: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/1c02414da0e37946.
Report an issue: GitHub.