argoproj/argo-workflows · error
template '%s' type is unknown
Error message
template '%s' type is unknown
What it means
During template resolution, ResolveTemplate fetches a template from a holder (workflow spec, workflow template, cluster workflow template, or stored template) and checks its type. If the resolved template's type is wfv1.TemplateTypeUnknown — i.e. the template exists but has no recognizable type (container, script, steps, dag, suspend, etc.) — resolution fails. This catches templates that are defined but effectively empty/unusable.
Source
Thrown at workflow/templateresolution/context.go:252
}
inlineResourceName = tmplRef.Name
}
err = tplCtx.workflow.SetStoredInlineTemplate(inlineScope, inlineResourceName, newTmpl)
if err != nil {
tplCtx.log.WithError(err).Error(ctx, "Failed to store the inline template")
}
}
tmpl = newTmpl
}
// Update the template base of the context.
newTmplCtx, err := tplCtx.WithTemplateHolder(ctx, tmplHolder)
if err != nil {
return nil, nil, false, err
}
if tmpl.GetType() == wfv1.TemplateTypeUnknown {
return nil, nil, false, fmt.Errorf("template '%s' type is unknown", tmpl.Name)
}
return newTmplCtx, tmpl, templateStored, nil
}
// WithTemplateHolder creates new context with a template base of a given template holder.
func (tplCtx *TemplateContext) WithTemplateHolder(ctx context.Context, tmplHolder wfv1.TemplateReferenceHolder) (*TemplateContext, error) {
tmplRef := tmplHolder.GetTemplateRef()
if tmplRef != nil {
tmplName := tmplRef.Name
if tmplRef.ClusterScope {
return tplCtx.WithClusterWorkflowTemplate(ctx, tmplName)
}
return tplCtx.WithWorkflowTemplate(ctx, tmplName)
}
return tplCtx.WithTemplateBase(tplCtx.tmplBase), nil
}
View on GitHub (pinned to 35bff19146)
Solutions
- Give the referenced template a valid type body (container, script, steps, dag, suspend, etc.) in the WorkflowTemplate
- Verify the template name in templateRef/template points at the intended template (kubectl get workflowtemplate -o yaml)
- Re-apply the WorkflowTemplate CRD/version so fields deserialize correctly, then resubmit the workflow
Example fix
// before (WorkflowTemplate)
templates:
- name: main
{}
// after
templates:
- name: main
container:
image: alpine
command: [echo, hello] Defensive patterns
Strategy: validation
Validate before calling
for _, t := range wt.Spec.Templates {
if t.GetType() == wfv1.TemplateTypeUnknown {
return fmt.Errorf("template %q in %s has no type body", t.Name, wt.Name)
}
} Type guard
func hasKnownTemplateType(t *wfv1.Template) bool {
return t.GetType() != wfv1.TemplateTypeUnknown
} Try / catch
wf, err := client.ArgoprojV1alpha1().Workflows(ns).Create(ctx, wf, metav1.CreateOptions{})
if err != nil && strings.Contains(err.Error(), "type is unknown") {
// inspect the referenced WorkflowTemplate for an empty template body
} Prevention
- Always give templates a concrete body (container/script/steps/dag/...) before referencing them
- Run argo lint on WorkflowTemplates in CI before workflows reference them
- Keep the WorkflowTemplate CRD and controller versions in sync
When it happens
Trigger: templateRef/template name resolves to a template whose spec lacks any type-defining field (no container, script, steps, dag, resource, suspend, data, http, plugin), e.g. an empty template {} in a WorkflowTemplate referenced via workflowTemplateRef or a stored template whose type could not be derived.
Common situations: Referencing the wrong template name in a WorkflowTemplate; a template with only metadata and no body; CRD/schema version mismatch where template fields fail to deserialize so type is lost; copy-pasted placeholder templates.
Related errors
- failed to get retry strategy: %w
- cron schedules must consist of 5 values only
- ${e.Usage()}
- --completed and --running cannot be used together
- invalid cache key: %s
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/71b7bf6091c72f0d.
Report an issue: GitHub.