argoproj/argo-workflows · error
workflows must use workflowTemplateRef to be executed when…
Error message
workflows must use workflowTemplateRef to be executed when the controller is in reference mode
What it means
When the controller is configured with workflowRestrictions.templateReferencing: Strict/Secure (reference mode), it rejects any workflow that does not use workflowTemplateRef. The reconciliation marks the workflow Error with this message and returns it.
Solutions
- Set spec.workflowTemplateRef.name on the workflow, moving its spec content into a WorkflowTemplate
- Remove or relax the workflowRestrictions.templateReferencing setting in the controller ConfigMap if inline specs are allowed
- Update CI/templates so all submissions go through WorkflowTemplates
Example fix
// before (controller config)
workflowRestrictions:
templateReferencing: Strict
// with inline-spec workflow -> either remove restriction or use:
// after
spec:
workflowTemplateRef:
name: my-template Defensive patterns
Strategy: validation
Validate before calling
if controllerConfig.WorkflowRestrictions != nil && wf.Spec.WorkflowTemplateRef == nil {
return fmt.Errorf("reference mode enabled: workflow must use workflowTemplateRef")
} Try / catch
if strings.Contains(err.Error(), "reference mode") {
// resubmit using a WorkflowTemplate reference
} Prevention
- Know your controller's workflowRestrictions config
- Standardize submissions through WorkflowTemplates
- Add CI linting that requires workflowTemplateRef in restricted namespaces
When it happens
Trigger: Submitting a workflow with an inline spec (no spec.workflowTemplateRef) to a controller whose config sets workflowRestrictions.templateReferencing, causing MustUseReference() to be true during operate().
Common situations: Namespace-wide policy enforcement enabled but legacy inline-spec workflows still exist; CI pipelines submitting hand-written specs after an admin hardened the controller config.
Related errors
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/59a2463d120b8666.
Report an issue: GitHub.
Appendix: source
Thrown at workflow/controller/operator.go:4502
// When workflow restrictions require template referencing (Strict/Secure mode),
// reject workflows that set any non-allowed fields, as they could override
// security settings defined in the WorkflowTemplate.
if woc.controller.Config.WorkflowRestrictions.MustUseReference() { // not-woc-misuse: intentionally checking the user-submitted spec
if err := wfutil.ValidateUserOverrides(&woc.wf.Spec); err != nil { //nolint:forbidigo // not-woc-misuse
ctx = woc.markWorkflowError(ctx, err)
return ctx, err
}
}
err := woc.setStoredWfSpec(ctx)
if err != nil {
ctx = woc.markWorkflowError(ctx, err)
return ctx, err
}
woc.execWf = &wfv1.Workflow{Spec: *woc.wf.Status.StoredWorkflowSpec.DeepCopy()}
woc.volumes = woc.execWf.Spec.DeepCopy().Volumes
setWfTemplateLabel(woc.wf)
case woc.controller.Config.WorkflowRestrictions.MustUseReference():
err := fmt.Errorf("workflows must use workflowTemplateRef to be executed when the controller is in reference mode")
ctx = woc.markWorkflowError(ctx, err)
return ctx, err
default:
err := woc.controller.setWorkflowDefaults(woc.wf)
if err != nil {
ctx = woc.markWorkflowError(ctx, err)
return ctx, err
}
woc.volumes = woc.wf.Spec.DeepCopy().Volumes //nolint:forbidigo // not-woc-misuse
}
// Perform one-time workflow validation
if woc.wf.Status.Phase == wfv1.WorkflowUnknown {
validateOpts := validate.Opts{}
wftmplGetter := templateresolution.WrapWorkflowTemplateInterface(woc.controller.wfclientset.ArgoprojV1alpha1().WorkflowTemplates(woc.wf.Namespace))
cwftmplGetter := templateresolution.WrapClusterWorkflowTemplateInterface(woc.controller.wfclientset.ArgoprojV1alpha1().ClusterWorkflowTemplates())
// Validate the execution wfSpecView on GitHub (pinned to 35bff19146)