argoproj/argo-workflows · critical

no Retry Node found by the name of %s; wf.Status.Nodes=%+v

Error message

no Retry Node found by the name of %s;  wf.Status.Nodes=%+v

What it means

Immediately after re-reading the current node, executeTemplate re-fetches the parent retry node (identified by retryNodeName) so it can fold a completed child attempt's status back into the retry parent. If the retry node cannot be found by name in wf.Status.Nodes, the controller logs the error, marks the workflow as Error, and returns. Like its sibling error, this indicates inconsistent workflow node status.

Source

Thrown at workflow/controller/operator.go:2610

	if node.Fulfilled() {
		woc.controller.syncManager.Release(ctx, woc.wf, node.ID, processedTmpl.Synchronization)
	}

	retrieveNode, retrieveErr := woc.wf.GetNodeByName(node.Name)
	if retrieveErr != nil {
		nodeErr := fmt.Errorf("no Node found by the name of %s;  wf.Status.Nodes=%+v", node.Name, woc.wf.Status.Nodes)
		woc.log.Error(ctx, nodeErr.Error())
		woc.markWorkflowError(ctx, nodeErr)
		return node, nodeErr
	}
	node = retrieveNode

	// Swap the node back to retry node
	if retryNodeName != "" {
		retryNode, getErr := woc.wf.GetNodeByName(retryNodeName)
		if getErr != nil {
			retryErr := fmt.Errorf("no Retry Node found by the name of %s;  wf.Status.Nodes=%+v", retryNodeName, woc.wf.Status.Nodes)
			woc.log.Error(ctx, retryErr.Error())
			woc.markWorkflowError(ctx, retryErr)
			return node, retryErr
		}

		if !retryNode.Phase.Fulfilled(retryNode.TaskResultSynced) && node.Phase.Fulfilled(node.TaskResultSynced) { // if the retry child has completed we need to update the parent's status
			retryNode, err = woc.executeTemplate(ctx, retryNodeName, orgTmpl, tmplCtx, args, opts)
			if err != nil {
				return woc.markNodeError(ctx, node.Name, err), err
			}
		}

		if !node.Phase.Fulfilled(node.TaskResultSynced) && node.IsDaemoned() {
			retryNode = woc.markNodePhase(ctx, retryNodeName, node.Phase)
			if node.IsDaemoned() { // markNodePhase doesn't pass the Daemoned field
				retryNode.Daemoned = new(true)
			}
		}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check wf.Status.Nodes in kubectl for the retry node name from the message; confirm whether it is truly gone.
  2. Run argo retry <name> to rebuild retry node status from existing pods.
  3. Avoid manual kubectl edits to workflow status; resubmit the workflow if status was corrupted.
  4. Ensure controller and CRDs come from the same release (reapply manifests/install.yaml after upgrade).
  5. Review controller logs around hydration/offloading; upgrade to the latest patch of your Argo Workflows series.
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on a retried task's parent, verify the retry node exists
wf, _ := wfClient.ArgoprojV1alpha1().Workflows(ns).Get(ctx, name, metav1.GetOptions{})
if wf.Status.Nodes.Find(func(n wfv1.NodeStatus) bool { return n.Name == retryNodeName }) == nil {
	return fmt.Errorf("retry node %q missing; run argo retry", retryNodeName)
}

Prevention

When it happens

Trigger: A template using retryStrategy executes a new attempt; executeTemplate resolves retryNodeName via wf.GetNodeByName and fails because the retry-parent node is absent from wf.Status.Nodes. Raised through executeDAGTask, hooks, onExit, or operate().

Common situations: Retried tasks on very large workflows where status was compressed/offloaded or nodes pruned; manual status edits removing the retry parent; controller/CRD version skew after upgrade corrupting node maps.

Related errors


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