{"record":{"id":"80f9d69057ece49b","repo":"argoproj/argo-workflows","slug":"can-t-process-artifact-gc-strategy-s-template-na","errorCode":null,"errorMessage":"can't process Artifact GC Strategy %s: template name %q belonging to node %+v not found","messagePattern":"can't process Artifact GC Strategy (.+?): template name %q belonging to node %\\+v not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/artifact_gc.go","lineNumber":188,"sourceCode":"\t\t}\n\t\tif _, found := groupedByPod[podName]; !found {\n\t\t\tgroupedByPod[podName] = make(templatesToArtifacts)\n\t\t}\n\t\t// get the Template for the Artifact\n\t\tnode, nodeErr := woc.wf.Status.Nodes.Get(artifactSearchResult.NodeID)\n\t\tif nodeErr != nil {\n\t\t\twoc.log.WithField(\"nodeID\", artifactSearchResult.NodeID).Error(ctx, \"Was unable to obtain node\")\n\t\t\treturn fmt.Errorf(\"can't process Artifact GC Strategy %s: node ID %q not found in Status\", strategy, artifactSearchResult.NodeID)\n\t\t}\n\t\ttemplateName := util.GetTemplateFromNode(*node)\n\t\tif templateName == \"\" {\n\t\t\treturn fmt.Errorf(\"can't process Artifact GC Strategy %s: node %+v has an unnamed template\", strategy, node)\n\t\t}\n\t\ttemplate, found := templatesByName[templateName]\n\t\tif !found {\n\t\t\ttemplate = woc.wf.GetTemplateByName(templateName)\n\t\t\tif template == nil {\n\t\t\t\treturn fmt.Errorf(\"can't process Artifact GC Strategy %s: template name %q belonging to node %+v not found\", strategy, templateName, node)\n\t\t\t}\n\t\t\ttemplatesByName[templateName] = template\n\t\t}\n\n\t\tif _, found := groupedByPod[podName][template.Name]; !found {\n\t\t\tgroupedByPod[podName][template.Name] = make(wfv1.ArtifactSearchResults, 0)\n\t\t}\n\n\t\tgroupedByPod[podName][template.Name] = append(groupedByPod[podName][template.Name], artifactSearchResult)\n\t}\n\n\t// start up a separate Pod with a separate set of ArtifactGCTasks for it to use for each unique Service Account/metadata\n\tfor podName, templatesToArtList := range groupedByPod {\n\t\ttasks := make([]*wfv1.WorkflowArtifactGCTask, 0)\n\n\t\tfor templateName, artifacts := range templatesToArtList {\n\t\t\ttemplate := templatesByName[templateName]\n\t\t\twoc.addTemplateArtifactsToTasks(ctx, podName, &tasks, template, artifacts)","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/artifact_gc.go#L170-L206","documentation":"During Artifact Garbage Collection, the controller groups artifacts to delete by the template that produced them. It resolves each node's template name via wf.GetTemplateByName; if the lookup returns nil the controller cannot determine the artifact's archive location and aborts processing of the GC strategy. This is thrown from processArtifactGCStrategy in workflow/controller/artifact_gc.go:188.","triggerScenarios":"A node's stored template name (from util.GetTemplateFromNode) does not match any template in woc.wf.Spec.Templates or Status.StoredTemplates when the GC strategy is processed (on workflow completion or deletion).","commonSituations":"Workflows submitted with templates later pruned from a referenced WorkflowTemplate; upgrades/downgrades where StoredTemplates were not recorded (older or migrated workflows); hand-edited Workflow Status; workflows restored from archive without full stored template state; controller version differences in GetTemplateFromNode.","solutions":["Ensure any WorkflowTemplate referenced by the workflow still contains the template that produced the artifacts; restore the missing template before deleting the workflow.","Check wf.Status.StoredTemplates on the Workflow object (kubectl get wf <name> -o yaml) — if the template is missing there, the workflow was created by a version that didn't store templates; re-run or recreate the workflow.","Set spec.artifactGC.forceFinalizerRemoval: true on the workflow to skip artifact GC and let deletion proceed, manually deleting artifacts.","Upgrade Argo Workflows to a version containing the template-resolution fix and restart the controller."],"exampleFix":"// before: workflow references a WorkflowTemplate whose 'build' template was deleted\ntemplateRef: my-wftpl/build  # template no longer exists -> GC fails\n// after: restore the template in the WorkflowTemplate (or pin with stored templates)\nkubectl patch workflowtemplate my-wftpl --type merge -p '{\"spec\":{\"templates\":[{\"name\":\"build\", ...}]}}'","handlingStrategy":"validation","validationCode":"// Before deleting a workflow with artifact GC, confirm all referenced templates exist\nwf, _ := wfClient.ArgoprojV1alpha1().Workflows(ns).Get(ctx, name, metav1.GetOptions{})\nfor _, node := range wf.Status.Nodes {\n    tn := node.TemplateName\n    if tn != \"\" && wf.GetTemplateByName(tn) == nil {\n        // template missing — GC will fail; restore it or set forceFinalizerRemoval\n    }\n}","typeGuard":"func templateExists(wf *wfv1.Workflow, name string) bool { return wf.GetTemplateByName(name) != nil }","tryCatchPattern":"if err := deleteWorkflow(ctx, name); strings.Contains(err.Error(), \"template name\") { /* restore template or set spec.artifactGC.forceFinalizerRemoval and retry */ }","preventionTips":["Never delete templates from a WorkflowTemplate while workflows referencing it still have the artifacts-gc finalizer.","Use argo lint on WorkflowTemplates before editing to ensure in-flight workflows still resolve templates.","Prefer workflow-level spec.artifactGC so strategies don't depend on artifact-level template state.","Pin StoredTemplates by keeping workflows on a controller version that stores templates on submit."],"tags":["kubernetes","artifact-gc","workflow-controller","template-resolution"],"backgroundTag":"template-not-found","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"}