{"record":{"id":"e37d59794ea15b9c","repo":"apache/dolphinscheduler","slug":"the-task-relation-from-pretask-getname","errorCode":null,"errorMessage":"\"The task relation from \" + preTask.getName() + \" to \" + postTask.getName() + \" is already exists\"","messagePattern":"\"The task relation from \" \\+ preTask\\.getName\\(\\) \\+ \" to \" \\+ postTask\\.getName\\(\\) \\+ \" is already exists\"","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/graph/WorkflowGraph.java","lineNumber":138,"sourceCode":"    }\n\n    private void addTaskEdge(List<WorkflowTaskRelation> workflowTaskRelations) {\n        for (WorkflowTaskRelation workflowTaskRelation : workflowTaskRelations) {\n            long pre = workflowTaskRelation.getPreTaskCode();\n            long post = workflowTaskRelation.getPostTaskCode();\n            if (pre > 0 && post > 0) {\n\n                if (!taskDefinitionCodeMap.containsKey(pre)) {\n                    throw new IllegalArgumentException(\"Cannot find task: \" + pre);\n                }\n                if (!taskDefinitionCodeMap.containsKey(post)) {\n                    throw new IllegalArgumentException(\"Cannot find task: \" + post);\n                }\n                TaskDefinition preTask = checkNotNull(taskDefinitionCodeMap.get(pre), \"Cannot find task: \" + pre);\n                TaskDefinition postTask = checkNotNull(taskDefinitionCodeMap.get(post), \"Cannot find task: \" + pre);\n                List<String> predecessorsTasks = predecessors.get(postTask.getName());\n                if (predecessorsTasks.contains(preTask.getName())) {\n                    throw new IllegalArgumentException(\"The task relation from \" + preTask.getName() + \" to \"\n                            + postTask.getName() + \" is already exists\");\n                }\n                predecessorsTasks.add(preTask.getName());\n\n                List<String> successTasks = successors.get(preTask.getName());\n                if (successTasks.contains(postTask.getName())) {\n                    throw new IllegalArgumentException(\"The task relation from \" + preTask.getName() + \" to \"\n                            + postTask.getName() + \" is already exists\");\n                }\n                successTasks.add(postTask.getName());\n            }\n\n            if (pre <= 0 && post <= 0) {\n                throw new IllegalArgumentException(\"The task relation from \" + pre + \" to \" + post + \" is invalid\");\n            }\n\n        }\n    }","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/graph/WorkflowGraph.java#L120-L156","documentation":"addTaskEdge rejects duplicate relations: after looking up both tasks, if the post task's predecessor list already contains the pre task's name, the same edge is being added twice, so it throws this IllegalArgumentException. Duplicate edges would double-count dependencies during DAG traversal.","triggerScenarios":"Constructing WorkflowGraph with t_ds_workflow_task_relation rows (or an in-memory relation list) containing the same (preTaskCode, postTaskCode) pair more than once.","commonSituations":"Duplicated relation rows created by a failed/retried save or import; re-running an import without deduplication; joining relations to task definitions in SQL producing duplicate rows.","solutions":["Deduplicate the relations by (preTaskCode, postTaskCode) before constructing the graph","Check t_ds_workflow_task_relation for duplicate (pre_task_code, post_task_code) rows and remove extras","Add a unique constraint on (workflow_definition_code, pre_task_code, post_task_code) to prevent recurrence","If parsing relations from JSON, use a Set keyed on the code pair during deserialization"],"exampleFix":"// before\nnew WorkflowGraph(tasks, relations); // (100 -> 200) appears twice\n// after\nSet<String> seen = new HashSet<>();\nList<WorkflowTaskRelation> distinct = relations.stream()\n        .filter(r -> seen.add(r.getPreTaskCode() + \"->\" + r.getPostTaskCode()))\n        .collect(Collectors.toList());\nWorkflowGraph g = new WorkflowGraph(tasks, distinct);","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (WorkflowTaskRelation r : relations) {\n    String key = r.getPreTaskCode() + \"->\" + r.getPostTaskCode();\n    if (!seen.add(key)) throw new IllegalStateException(\"Duplicate relation: \" + key);\n}","typeGuard":null,"tryCatchPattern":"try {\n    WorkflowGraph graph = new WorkflowGraph(taskDefinitions, relations);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"is already exists\")) log.error(\"Duplicate edge in workflow: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["Use a Set/unique key when collecting relations from any source","Add a unique DB constraint on (workflow, pre_task_code, post_task_code)","Guard import/retry logic against re-inserting relation rows","Deduplicate relations loaded via joins that can fan out rows"],"tags":["workflow-graph","duplicate-edge","dag"],"backgroundTag":"invalid-argument-value","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}