argoproj/argo-workflows · error
can't process Artifact GC Strategy %s: template name %q belo
Error message
can't process Artifact GC Strategy %s: template name %q belonging to node %+v not found
What it means
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.
Source
Thrown at workflow/controller/artifact_gc.go:188
}
if _, found := groupedByPod[podName]; !found {
groupedByPod[podName] = make(templatesToArtifacts)
}
// get the Template for the Artifact
node, nodeErr := woc.wf.Status.Nodes.Get(artifactSearchResult.NodeID)
if nodeErr != nil {
woc.log.WithField("nodeID", artifactSearchResult.NodeID).Error(ctx, "Was unable to obtain node")
return fmt.Errorf("can't process Artifact GC Strategy %s: node ID %q not found in Status", strategy, artifactSearchResult.NodeID)
}
templateName := util.GetTemplateFromNode(*node)
if templateName == "" {
return fmt.Errorf("can't process Artifact GC Strategy %s: node %+v has an unnamed template", strategy, node)
}
template, found := templatesByName[templateName]
if !found {
template = woc.wf.GetTemplateByName(templateName)
if template == nil {
return fmt.Errorf("can't process Artifact GC Strategy %s: template name %q belonging to node %+v not found", strategy, templateName, node)
}
templatesByName[templateName] = template
}
if _, found := groupedByPod[podName][template.Name]; !found {
groupedByPod[podName][template.Name] = make(wfv1.ArtifactSearchResults, 0)
}
groupedByPod[podName][template.Name] = append(groupedByPod[podName][template.Name], artifactSearchResult)
}
// start up a separate Pod with a separate set of ArtifactGCTasks for it to use for each unique Service Account/metadata
for podName, templatesToArtList := range groupedByPod {
tasks := make([]*wfv1.WorkflowArtifactGCTask, 0)
for templateName, artifacts := range templatesToArtList {
template := templatesByName[templateName]
woc.addTemplateArtifactsToTasks(ctx, podName, &tasks, template, artifacts)View on GitHub (pinned to 35bff19146)
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.
Example fix
// before: workflow references a WorkflowTemplate whose 'build' template was deleted
templateRef: my-wftpl/build # template no longer exists -> GC fails
// after: restore the template in the WorkflowTemplate (or pin with stored templates)
kubectl patch workflowtemplate my-wftpl --type merge -p '{"spec":{"templates":[{"name":"build", ...}]}}' Defensive patterns
Strategy: validation
Validate before calling
// Before deleting a workflow with artifact GC, confirm all referenced templates exist
wf, _ := wfClient.ArgoprojV1alpha1().Workflows(ns).Get(ctx, name, metav1.GetOptions{})
for _, node := range wf.Status.Nodes {
tn := node.TemplateName
if tn != "" && wf.GetTemplateByName(tn) == nil {
// template missing — GC will fail; restore it or set forceFinalizerRemoval
}
} Type guard
func templateExists(wf *wfv1.Workflow, name string) bool { return wf.GetTemplateByName(name) != nil } Try / catch
if err := deleteWorkflow(ctx, name); strings.Contains(err.Error(), "template name") { /* restore template or set spec.artifactGC.forceFinalizerRemoval and retry */ } Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- can't find podInfo for podName %q
- failed to get WorkflowArtifactGCTask by key %q: %w
- can't find template with name %q
- failed to get pods from informer: %w
- ArtifactGCStrategy %q not valid
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/80f9d69057ece49b.
Report an issue: GitHub.