{"record":{"id":"66f75c0dac9c2704","repo":"argoproj/argo-workflows","slug":"critical-error-unable-to-find-s","errorCode":null,"errorMessage":"critical error; unable to find %s","messagePattern":"critical error; unable to find (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"workflow/controller/dag.go","lineNumber":397,"sourceCode":"\t\treturn node, nil\n\t}\n\n\t// set outputs from tasks in order for DAG templates to support outputs\n\tscope := createScope(tmpl)\n\tfor _, task := range tmpl.DAG.Tasks {\n\t\ttaskNode := dagCtx.getTaskNode(ctx, task.Name)\n\t\tif taskNode == nil {\n\t\t\t// Can happen when dag.target was specified\n\t\t\tcontinue\n\t\t}\n\n\t\tif taskNode.Type == wfv1.NodeTypeTaskGroup {\n\t\t\tchildNodes := make([]wfv1.NodeStatus, len(taskNode.Children))\n\t\t\tfor i, childID := range taskNode.Children {\n\t\t\t\tchildNode, childErr := woc.wf.Status.Nodes.Get(childID)\n\t\t\t\tif childErr != nil {\n\t\t\t\t\twoc.log.WithField(\"nodeID\", childID).Error(ctx, \"was unable to obtain node for nodeID\")\n\t\t\t\t\treturn nil, fmt.Errorf(\"critical error; unable to find %s\", childID)\n\t\t\t\t}\n\t\t\t\tchildNodes[i] = *childNode\n\t\t\t}\n\t\t\taggErr := woc.processAggregateNodeOutputs(scope, varkeys.TasksAggregate, task.Name, childNodes)\n\t\t\tif aggErr != nil {\n\t\t\t\twoc.log.Error(ctx, \"unable to processAggregateNodeOutputs\")\n\t\t\t\treturn nil, argoerrors.InternalWrapError(aggErr)\n\t\t\t}\n\t\t}\n\t\twoc.buildLocalScope(scope, varkeys.TasksNodeRef, task.Name, taskNode)\n\t\t// Skipped/omitted tasks produced no Outputs; populate their declared output parameters so that\n\t\t// DAG-level output aggregation (parameter refs and ValueFrom.Expression) can resolve them.\n\t\twoc.addSkippedNodeOutputsToScope(ctx, dagCtx.tmplCtx, scope, varkeys.TasksNodeRef, task.Name, taskNode, &task, false)\n\t\twoc.addOutputsToGlobalScope(ctx, taskNode.Outputs)\n\t}\n\toutputs, err := woc.getTemplateOutputsFromScope(ctx, tmpl, scope)\n\tif err != nil {\n\t\twoc.log.Error(ctx, \"unable to get outputs\")","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/dag.go#L379-L415","documentation":"This error is thrown by the DAG reconciler in executeDAG when it builds the child node list of a task-group node (a task with sub-tasks, i.e. withChildren/when-agg results). It looks up each child node ID in wf.Status.Nodes; if the ID is missing from the status map it logs 'was unable to obtain node for nodeID' and returns this critical error. The controller treats a missing child as a corrupted/inconsistent workflow state rather than a transient condition, so reconciliation of the DAG aborts.","triggerScenarios":"executeDAG iterates taskNode.Children for a NodeTypeTaskGroup node and calls wf.Status.Nodes.Get(childID), which fails because the child node ID referenced in taskNode.Children no longer exists in wf.Status.Nodes (e.g. the status was truncated/offloaded, pruned, or never created).","commonSituations":"Workflows whose status grew too large and was compressed/offloaded (large DAGs, huge outputs) causing node-map inconsistencies; manual edits to the Workflow object (kubectl edit/delete of nodes in status); controller bugs or upgrades where child node creation failed mid-reconcile; restoring archived workflows without full node status.","solutions":["Inspect the Workflow's wf.Status.Nodes (argo get / kubectl get wf <name> -o yaml) and confirm whether the child ID in the task-group's Children list is really missing; look at the controller logs for the nodeID field.","If the status was manually modified or corrupted, delete and resubmit the workflow from a known-good spec (argo resubmit / argo submit) rather than patching status.","Check controller version for known bugs around node offloading/hydration; upgrade to the latest patch release of your Argo Workflows version.","If the workflow pod is still running and only status is inconsistent, retrying the workflow (argo retry) can rebuild node state from existing pods.","Reduce node/status size (limit outputs, use S3/artifact logging, configure node status offloading) to avoid future status truncation."],"exampleFix":"// before: relying on possibly-missing node in status\nchildNode, childErr := woc.wf.Status.Nodes.Get(childID)\nif childErr != nil {\n\treturn nil, fmt.Errorf(\"critical error; unable to find %s\", childID)\n}\n// after: guard at caller / avoid hand-editing status; resubmit instead\n// kubectl delete wf <name> (keep pods) then:\n// argo resubmit <name> --restart-successful","handlingStrategy":"validation","validationCode":"// Validate before running: ensure every task-group child ID exists in status\n// (client-side check when inspecting a workflow)\nwf, _ := wfClient.ArgoprojV1alpha1().Workflows(ns).Get(ctx, name, metav1.GetOptions{})\nfor _, n := range wf.Status.Nodes {\n\tif n.Type == wfv1.NodeTypeTaskGroup {\n\t\tfor _, cid := range n.Children {\n\t\t\tif _, ok := wf.Status.Nodes[cid]; !ok {\n\t\t\t\treturn fmt.Errorf(\"child node %s missing from status; resubmit workflow\", cid)\n\t\t\t}\n\t\t}\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit Workflow status with kubectl edit/patch.","Enable node status offloading (configured offloadPersistentDB) so huge statuses don't get truncated.","Keep outputs small (don't attach entire logs as parameters) to limit node-status size.","Upgrade the controller promptly; watch release notes for node-status hydration fixes."],"tags":["kubernetes","argo-workflows","controller","dag","state-corruption"],"backgroundTag":"missing-node-status","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}