{"record":{"id":"3365bc4d6fab565c","repo":"argoproj/argo-workflows","slug":"failed-to-read-template-w","errorCode":null,"errorMessage":"failed to read template: %w","messagePattern":"failed to read template: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/argoexec/commands/emissary.go","lineNumber":155,"sourceCode":"\t// the template. Gated on an env var so legacy pods are unaffected.\n\twaitForReady := os.Getenv(common.EnvVarWaitForReady) == \"true\"\n\tif waitForReady {\n\t\tif waitErr := waitForSupervisorReady(ctx); waitErr != nil {\n\t\t\t// Distinct exit code so the controller attributes the failure\n\t\t\t// to supervisor pre-main setup rather than the user command.\n\t\t\t// The process exit code (not just the exitcode file) must carry\n\t\t\t// the sentinel, because inferFailedReason keys off the container's\n\t\t\t// terminated exit code; wrap so main propagates 65 while keeping\n\t\t\t// waitErr's message.\n\t\t\texitCode = common.ExitCodeSupervisorPreMainFailure\n\t\t\tlogger.WithError(waitErr).Error(ctx, \"supervisor failed before main container started\")\n\t\t\treturn argoerrors.NewExitErrWithCause(exitCode, waitErr)\n\t\t}\n\t}\n\n\tdata, err := readTemplate()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read template: %w\", err)\n\t}\n\n\ttemplate := &wfv1.Template{}\n\tif err = json.Unmarshal(data, template); err != nil {\n\t\treturn fmt.Errorf(\"failed to unmarshal template: %w\", err)\n\t}\n\n\t// In init-less pod mode, main can't use the legacy per-artifact\n\t// SubPath bind mount (kubelet races the supervisor's write). The\n\t// input-artifacts volume is mounted whole at /argo/inputs/artifacts\n\t// and the emissary symlinks each input artifact into its expected\n\t// path once supervisor has finished writing (guaranteed by the\n\t// ready-marker wait above). Only `main` runs this — ContainerSet\n\t// children and sidecars don't get artifact paths symlinked in.\n\tif waitForReady && containerName == common.MainContainerName {\n\t\tif stageErr := stageInputArtifacts(ctx, template); stageErr != nil {\n\t\t\t// As above: propagate the sentinel as the process exit code so\n\t\t\t// inferFailedReason attributes this to supervisor pre-main setup.","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/cmd/argoexec/commands/emissary.go#L137-L173","documentation":"runEmissary needs the Workflow Template (the pod's template JSON) to know ContainerSet dependencies and artifact staging paths. readTemplate() first tries the file /var/run/argo/template (written by the init container, or by the supervisor in init-less mode) and falls back to the ARGO_TEMPLATE env var. This error is thrown when neither source is readable — the file read failed with an error other than NotExist (e.g. permission denied), or the file is missing AND ARGO_TEMPLATE is not set/resolvable.","triggerScenarios":"ARGO_template file missing and ARGO_TEMPLATE unset (pod created by a controller path that expected the file only); /var/run/argo/template unreadable due to permissions; in init-less mode the supervisor never wrote the template before emissary read it and the ARGO_TEMPLATE fallback is absent; the template-env offload sentinel cannot be resolved from the config mount.","commonSituations":"Version skew between controller and executor around init-less/supervisor mode; custom pod patches removing the /var/run/argo volume or the ARGO_TEMPLATE env; pod started before init container completed in a modified layout; securityContext blocking /var/run/argo reads.","solutions":["Check the pod spec: the main/supervisor container must have ARGO_TEMPLATE set or the /var/run/argo volume mounted where the template file is written.","Verify supervisor/init completed: `kubectl exec <pod> -c init/supervisor -- ls -l /var/run/argo/template` and check its logs.","Align controller and executor images to the same Argo Workflows version.","Ensure waitForReady/supervisor readiness gating is intact (emissary waits on the ready marker before reading) — do not patch it out.","Confirm the config-map offload dir (common.EnvConfigMountPath) is mounted if ARGO_TEMPLATE uses the offload sentinel."],"exampleFix":"// before: custom patch removed the template env from main\ncontainers:\n  - name: main\n    env: []            # ARGO_TEMPLATE gone, /var/run/argo/template not written yet\n// after: leave controller-managed env/volumes intact\ncontainers:\n  - name: main\n    env:\n      - name: ARGO_TEMPLATE\n        valueFrom: { ... }   # controller-injected","handlingStrategy":"try-catch","validationCode":"// Detect a usable template source before proceeding:\nfunc templateSourceAvailable() error {\n\tif _, err := os.Stat(\"/var/run/argo/template\"); err == nil {\n\t\treturn nil\n\t}\n\tif _, ok := os.LookupEnv(\"ARGO_TEMPLATE\"); ok {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"neither /var/run/argo/template nor ARGO_TEMPLATE available\")\n}","typeGuard":null,"tryCatchPattern":"data, err := readTemplate()\nif err != nil {\n\tif errors.Is(err, os.ErrPermission) {\n\t\tlogger.WithError(err).Error(ctx, \"template file unreadable — check /var/run/argo mount and securityContext\")\n\t} else if strings.Contains(err.Error(), \"neither\") {\n\t\tlogger.WithError(err).Error(ctx, \"no template source: init/supervisor did not write it and ARGO_TEMPLATE unset — check pod spec and version skew\")\n\t}\n\treturn err\n}","preventionTips":["Keep controller, argo-server and executor on the same release version.","Do not remove the /var/run/argo volume mount or ARGO_TEMPLATE env from pod specs.","In init-less mode, keep the supervisor readiness wait (EnvVarWaitForReady) enabled so main never races the template write.","Ensure the config mount for template offload (common.EnvConfigMountPath) is present when templates are large.","Alert on executor logs mentioning 'failed to read template' — it indicates layout/upgrade drift."],"tags":["kubernetes","executor","filesystem","env-var","pod-lifecycle","argo-workflows"],"backgroundTag":"missing-template-source","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}