argoproj/argo-workflows · error

was unable to obtain childNode for %s

Error message

was unable to obtain childNode for %s

What it means

While evaluating a completed step group, the controller iterates node.Children to fetch each child node from Status.Nodes. If a child ID is missing from status (inconsistent/compressed/offloaded state), it logs and returns this error, aborting the step-group evaluation.

Source

Thrown at workflow/controller/steps.go:330

		}
		if childNode != nil {
			nodeSteps[childNodeName] = step
			woc.addChildNode(ctx, sgNodeName, childNodeName)
		}
	}

	node, err = woc.wf.GetNodeByName(sgNodeName)
	if err != nil {
		return nil, err
	}
	// Return if not all children completed
	completed := true
	for _, childNodeID := range node.Children {
		childNode, err := woc.wf.Status.Nodes.Get(childNodeID)
		if err != nil {
			errorMsg := fmt.Sprintf("was unable to obtain childNode for %s", childNodeID)
			woc.log.Error(ctx, errorMsg)
			return nil, fmt.Errorf("%s", errorMsg)
		}
		step := nodeSteps[childNode.Name]
		varkeys.StepsNodeRef.Status.Set(stepsCtx.scope.scope, string(childNode.Phase), childNode.DisplayName)
		hookCompleted, err := woc.executeTmplLifeCycleHook(ctx, stepsCtx.scope, step.Hooks, childNode, stepsCtx.boundaryID, stepsCtx.tmplCtx, varkeys.StepsNodeRef, step.Name)
		if err != nil {
			woc.markNodeError(ctx, node.Name, err)
		}
		// Check all hooks are completed
		if !hookCompleted {
			return node, nil
		}

		if !childNode.Fulfilled() {
			completed = false
		} else if childNode.Completed() {
			hasOnExitNode, onExitNode, err := woc.runOnExitNode(ctx, step.GetExitHook(woc.execWf.Spec.Arguments), childNode, stepsCtx.boundaryID, stepsCtx.tmplCtx, varkeys.StepsNodeRef, step.Name, stepsCtx.scope)
			// see https://github.com/argoproj/argo-workflows/issues/14031,
			// we should return error otherwise the node will get stuck

View on GitHub (pinned to 35bff19146)

Solutions

  1. Re-run/retry the workflow to rebuild consistent status
  2. Check whether the workflow status exceeds size limits (offloaded to DB) and ensure the reader hydrates via the hydrator
  3. Avoid manual kubectl edits of status.nodes; report corruption to Argo maintainers
Defensive patterns

Strategy: try-catch

Try / catch

if strings.Contains(err.Error(), "was unable to obtain childNode") {
    // hydrate workflow status via the hydrator before reading nodes, then retry
}

Prevention

When it happens

Trigger: A child node ID recorded on the step-group node is not present in wf.Status.Nodes during executeStepGroup — e.g. status was truncated/offloaded without hydration, or nodes were corrupted/deleted.

Common situations: Very large workflows whose node status was compressed/offloaded and read without hydrating; manual edits to Workflow status; controller bugs dropping nodes.

Related errors


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