argoproj/argo-workflows · error
404
404
Error message
template %s not found
What it means
TemplateContext.GetTemplateByName resolves a template by name from the template base (workflow, WorkflowTemplate, or ClusterWorkflowTemplate already loaded into context). If no template with that name exists in the base, it returns a 404 CodeNotFound error so callers (validation, GetTemplate) fail with a clear not-found message.
Source
Thrown at workflow/templateresolution/context.go:107
// NewContextFromClientSet returns new Context.
func NewContextFromClientSet(wftmplClientset typed.WorkflowTemplateInterface, clusterWftmplClient typed.ClusterWorkflowTemplateInterface, tmplBase wfv1.TemplateHolder, workflow *wfv1.Workflow, log logging.Logger) *TemplateContext {
return &TemplateContext{
wftmplGetter: WrapWorkflowTemplateInterface(wftmplClientset),
cwftmplGetter: WrapClusterWorkflowTemplateInterface(clusterWftmplClient),
tmplBase: tmplBase,
workflow: workflow,
log: log,
}
}
// GetTemplateByName returns a template by name in the context.
func (tplCtx *TemplateContext) GetTemplateByName(ctx context.Context, name string) (*wfv1.Template, error) {
tplCtx.log.WithField("name", name).Debug(ctx, "Getting the template by name")
tmpl := tplCtx.tmplBase.GetTemplateByName(name)
if tmpl == nil {
return nil, errors.Errorf(errors.CodeNotFound, "template %s not found", name)
}
podMetadata := tplCtx.tmplBase.GetPodMetadata()
tplCtx.addPodMetadata(podMetadata, tmpl)
return tmpl.DeepCopy(), nil
}
func (tplCtx *TemplateContext) GetTemplateGetterFromRef(ctx context.Context, tmplRef *wfv1.TemplateRef) (wfv1.TemplateHolder, error) {
if tmplRef.ClusterScope {
return tplCtx.cwftmplGetter.Get(ctx, tmplRef.Name)
}
return tplCtx.wftmplGetter.Get(ctx, tmplRef.Name)
}
// GetTemplateFromRef returns a template found by a given template ref.
func (tplCtx *TemplateContext) GetTemplateFromRef(ctx context.Context, tmplRef *wfv1.TemplateRef) (*wfv1.Template, error) {
tplCtx.log.Debug(ctx, "Getting the template from ref")View on GitHub (pinned to 35bff19146)
Solutions
- Correct the template name in the step/task/templateRef
- Verify the referenced WorkflowTemplate actually contains the template
- Run `argo lint` before submitting to catch missing templates
Example fix
// before - name: step-a template: build-image # does not exist // after - name: step-a template: build # matches templates[].name in the spec
Defensive patterns
Strategy: validation
Validate before calling
// pre-check that the template exists in the holder
names := set(tmplBase.Templates.map(t => t.Name))
for (const ref of allTemplateRefs(wf)) {
if (!names.has(ref)) throw new Error(`template ${ref} not found`)
} Try / catch
tmpl, err := tplCtx.GetTemplateByName(ctx, name)
if err != nil {
var nf *errors.ArgoError
if errors.As(err, &nf) && nf.Code() == 404 {
return fmt.Errorf("template %q missing from spec; run argo lint", name)
}
return err
} Prevention
- Run `argo lint` before every submit
- Keep template names consistent with a naming convention
- Check templateRef targets exist in the named WorkflowTemplate/ClusterWorkflowTemplate
When it happens
Trigger: Calling GetTemplate/GetTemplateByName with a template name that doesn't exist in the referenced template holder; validateTemplateHolder on a spec whose templates list lacks the referenced name.
Common situations: Typos in template names; steps/tasks referencing templates removed during refactoring; templateRef pointing to a template that exists in a different WorkflowTemplate than the one named.
Related errors
- failed to get workflow template: %w
- archived workflow '%s' not found
- failed to read container args file %s: %w
- failed to unmarshal container args: %w
- failed to read template: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e58ff407684dba57.
Report an issue: GitHub.