{"record":{"id":"36a461ce793af150","repo":"argoproj/argo-workflows","slug":"duplicated-nodename-s","errorCode":null,"errorMessage":"duplicated nodeName %s","messagePattern":"duplicated nodeName (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/sorting/topological_sorting.go","lineNumber":18,"sourceCode":"package sorting\n\nimport (\n\t\"fmt\"\n)\n\ntype TopologicalSortingNode struct {\n\tNodeName     string\n\tDependencies []string\n}\n\nfunc TopologicalSorting(graph []*TopologicalSortingNode) ([]*TopologicalSortingNode, error) {\n\tpriorNodeCountMap := make(map[string]int, len(graph))               // nodeName -> priorNodeCount\n\tnextNodeMap := make(map[string][]string, len(graph))                // nodeName -> nextNodeList\n\tnodeNameMap := make(map[string]*TopologicalSortingNode, len(graph)) // nodeName -> node\n\tfor _, node := range graph {\n\t\tif _, ok := nodeNameMap[node.NodeName]; ok {\n\t\t\treturn nil, fmt.Errorf(\"duplicated nodeName %s\", node.NodeName)\n\t\t}\n\t\tnodeNameMap[node.NodeName] = node\n\t\tpriorNodeCountMap[node.NodeName] = len(node.Dependencies)\n\t}\n\tfor _, node := range graph {\n\t\tfor _, dependency := range node.Dependencies {\n\t\t\tif _, ok := nodeNameMap[dependency]; !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid dependency %s\", dependency)\n\t\t\t}\n\t\t\tnextNodeMap[dependency] = append(nextNodeMap[dependency], node.NodeName)\n\t\t}\n\t}\n\n\tqueue := make([]*TopologicalSortingNode, len(graph))\n\thead, tail := 0, 0\n\tfor nodeName, priorNodeCount := range priorNodeCountMap {\n\t\tif priorNodeCount == 0 {\n\t\t\tqueue[tail] = nodeNameMap[nodeName]","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/util/sorting/topological_sorting.go#L1-L36","documentation":"TopologicalSorting builds a DAG from TopologicalSortingNode entries keyed by NodeName; duplicate NodeNames would corrupt the indegree/adjacency maps, so the algorithm rejects them immediately. Each node in the graph must be uniquely named before sorting.","triggerScenarios":"Passing a []*TopologicalSortingNode where two entries share the same NodeName (e.g. appending a node twice, or building the list per-template without including the node/step index in the name).","commonSituations":"DAG synchronization code appending boundary nodes that already exist; retry logic re-adding an entry for the same node; constructing dependencies for broadened nodes but reusing names across steps; unit-test fixtures that duplicate a node.","solutions":["Deduplicate the graph slice before calling TopologicalSorting (map by NodeName).","Make node names unique by qualifying them with their parent (e.g. group/template/step identifiers) as the controller does.","Fix loops that re-append the same node on retries; reuse the existing entry instead.","Fix the fixture in tests so each node appears once."],"exampleFix":"// before\ngraph = append(graph, node)\ngraph = append(graph, node) // duplicate\n// after\nseen := map[string]bool{}\nif !seen[node.NodeName] {\n    graph = append(graph, node)\n    seen[node.NodeName] = true\n}","handlingStrategy":"validation","validationCode":"func hasUniqueNames(graph []*sorting.TopologicalSortingNode) bool {\n    seen := map[string]bool{}\n    for _, n := range graph {\n        if seen[n.NodeName] { return false }\n        seen[n.NodeName] = true\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":"sorted, err := sorting.TopologicalSorting(graph)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"duplicated nodeName\") {\n        graph = dedupeByNodeName(graph)\n        sorted, err = sorting.TopologicalSorting(graph)\n    }\n    if err != nil { return err }\n}","preventionTips":["Build node names through one qualified-name helper (parent/child) so collisions cannot occur.","Deduplicate by NodeName right before sorting as an invariant check.","Avoid re-appending nodes in retry/patch code paths; update in place."],"tags":["go","dag","topological-sort","validation"],"backgroundTag":"duplicate-node-name","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}