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

  1. Ensure any WorkflowTemplate referenced by the workflow still contains the template that produced the artifacts; restore the missing template before deleting the workflow.
  2. 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.
  3. Set spec.artifactGC.forceFinalizerRemoval: true on the workflow to skip artifact GC and let deletion proceed, manually deleting artifacts.
  4. 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

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


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/80f9d69057ece49b. Report an issue: GitHub.