{"record":{"id":"fbe109bcd7975405","repo":"argoproj/argo-workflows","slug":"cannot-fetch-workflow-spec-without-workflowtemplat","errorCode":null,"errorMessage":"cannot fetch workflow spec without workflowTemplateRef","messagePattern":"cannot fetch workflow spec without workflowTemplateRef","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/operator.go","lineNumber":4451,"sourceCode":"\t\treturn false, nil\n\t}\n\n\tparentTemplate, templateStored, err := woc.GetTemplateByBoundaryID(ctx, boundaryID)\n\tif err != nil || parentTemplate == nil {\n\t\treturn false, err\n\t}\n\t// A new template was stored during resolution, persist it\n\tif templateStored {\n\t\twoc.updated = true\n\t}\n\n\tname := getStepOrDAGTaskName(nodeName)\n\treturn woc.hasOutputResultRef(ctx, name, parentTemplate), nil\n}\n\nfunc (woc *wfOperationCtx) fetchWorkflowSpec(ctx context.Context) (wfv1.WorkflowSpecHolder, error) {\n\tif woc.wf.Spec.WorkflowTemplateRef == nil { //nolint:forbidigo // not-woc-misuse\n\t\treturn nil, fmt.Errorf(\"cannot fetch workflow spec without workflowTemplateRef\")\n\t}\n\n\tvar specHolder wfv1.WorkflowSpecHolder\n\tvar err error\n\t// Logic for workflow refers Workflow template\n\tif woc.wf.Spec.WorkflowTemplateRef.ClusterScope { //nolint:forbidigo // not-woc-misuse\n\t\tif woc.controller.cwftmplInformer == nil {\n\t\t\twoc.log.WithError(err).Error(ctx, \"clusterWorkflowTemplate RBAC is missing\")\n\t\t\treturn nil, fmt.Errorf(\"cannot get resource clusterWorkflowTemplate at cluster scope\")\n\t\t}\n\t\twoc.controller.metrics.CountWorkflowTemplate(ctx, metrics.WorkflowNew, woc.wf.Spec.WorkflowTemplateRef.Name, woc.wf.Namespace, true) //nolint:forbidigo // not-woc-misuse\n\t\tspecHolder, err = woc.controller.cwftmplInformer.Lister().Get(woc.wf.Spec.WorkflowTemplateRef.Name)                                  //nolint:forbidigo // not-woc-misuse\n\t} else {\n\t\twoc.controller.metrics.CountWorkflowTemplate(ctx, metrics.WorkflowNew, woc.wf.Spec.WorkflowTemplateRef.Name, woc.wf.Namespace, false)  //nolint:forbidigo // not-woc-misuse\n\t\tspecHolder, err = woc.controller.wftmplInformer.Lister().WorkflowTemplates(woc.wf.Namespace).Get(woc.wf.Spec.WorkflowTemplateRef.Name) //nolint:forbidigo // not-woc-misuse\n\t}\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":4433,"sourceCodeEnd":4469,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/operator.go#L4433-L4469","documentation":"The controller's fetchWorkflowSpec only supports workflows whose spec uses workflowTemplateRef to source their spec from a WorkflowTemplate. If a workflow has an inline spec (no workflowTemplateRef), the controller cannot retrieve a spec holder and returns this error, aborting reconciliation of that workflow.","triggerScenarios":"Reconciling a Workflow whose Spec.WorkflowTemplateRef is nil while executing the code path that requires fetching the referenced template spec (e.g. template referencing / stored-spec resolution in operator.go).","commonSituations":"Users submit workflows with fully inline specs (the traditional style) while the controller or code path assumes template-based workflows; older workflows migrated before workflowTemplateRef existed; YAML that accidentally places workflowTemplateRef at the wrong nesting level so it is not parsed.","solutions":["Convert the workflow to reference a WorkflowTemplate by setting spec.workflowTemplateRef.name","Check the submitted YAML: workflowTemplateRef must be a direct child of spec, not nested elsewhere","If inline specs are intended, ensure the controller code path taken does not require fetching the template spec (not in reference/secure mode)"],"exampleFix":"// before\nspec:\n  entrypoint: main\n  templates:\n    - name: main\n      container:\n        image: alpine\n// after\nspec:\n  entrypoint: main\n  workflowTemplateRef:\n    name: my-template","handlingStrategy":"validation","validationCode":"if wf.Spec.WorkflowTemplateRef == nil {\n    return fmt.Errorf(\"workflow %s must set spec.workflowTemplateRef\", wf.Name)\n}","typeGuard":"func hasTemplateRef(wf *wfv1.Workflow) bool { return wf != nil && wf.Spec.WorkflowTemplateRef != nil }","tryCatchPattern":null,"preventionTips":["Always submit template-based workflows when using template referencing features","Run argo lint before submitting","Keep workflowTemplateRef at the correct YAML nesting under spec"],"tags":["kubernetes","argo-workflows","workflow-template","controller"],"backgroundTag":"missing-workflow-template-ref","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"}