apache/dolphinscheduler · error · IllegalArgumentException

"Cannot find task: " + pre

Error message

"Cannot find task: " + pre

What it means

addTaskEdge validates each WorkflowTaskRelation: if the relation has a positive preTaskCode, the code must exist in the graph's task code map, otherwise the edge would point at a task the graph does not contain. It throws this IllegalArgumentException naming the missing pre-task code.

Source

Thrown at dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/graph/WorkflowGraph.java:129

                .stream()
                .map(TaskDefinition::getName)
                .forEach(taskDefinition -> {
                    if (predecessors.containsKey(taskDefinition) || successors.containsKey(taskDefinition)) {
                        throw new IllegalArgumentException("The task " + taskDefinition + " is already exists");
                    }
                    predecessors.put(taskDefinition, new ArrayList<>());
                    successors.put(taskDefinition, new ArrayList<>());
                });
    }

    private void addTaskEdge(List<WorkflowTaskRelation> workflowTaskRelations) {
        for (WorkflowTaskRelation workflowTaskRelation : workflowTaskRelations) {
            long pre = workflowTaskRelation.getPreTaskCode();
            long post = workflowTaskRelation.getPostTaskCode();
            if (pre > 0 && post > 0) {

                if (!taskDefinitionCodeMap.containsKey(pre)) {
                    throw new IllegalArgumentException("Cannot find task: " + pre);
                }
                if (!taskDefinitionCodeMap.containsKey(post)) {
                    throw new IllegalArgumentException("Cannot find task: " + post);
                }
                TaskDefinition preTask = checkNotNull(taskDefinitionCodeMap.get(pre), "Cannot find task: " + pre);
                TaskDefinition postTask = checkNotNull(taskDefinitionCodeMap.get(post), "Cannot find task: " + pre);
                List<String> predecessorsTasks = predecessors.get(postTask.getName());
                if (predecessorsTasks.contains(preTask.getName())) {
                    throw new IllegalArgumentException("The task relation from " + preTask.getName() + " to "
                            + postTask.getName() + " is already exists");
                }
                predecessorsTasks.add(preTask.getName());

                List<String> successTasks = successors.get(preTask.getName());
                if (successTasks.contains(postTask.getName())) {
                    throw new IllegalArgumentException("The task relation from " + preTask.getName() + " to "
                            + postTask.getName() + " is already exists");
                }

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Reconcile t_ds_workflow_task_relation against t_ds_task_definition and remove relations whose pre/post task codes have no definition
  2. Load the task definitions from the same source/snapshot as the relations so they are consistent
  3. Before constructing the graph, filter relations whose pre or post codes are not in the task list and fix the definition data
  4. Catch IllegalArgumentException at construction to surface the inconsistent workflow definition for repair

Example fix

// before
new WorkflowGraph(taskDefinitions, relations); // relations reference deleted task 999
// after
Set<Long> codes = taskDefinitions.stream().map(TaskDefinition::getCode).collect(Collectors.toSet());
List<WorkflowTaskRelation> valid = relations.stream()
        .filter(r -> r.getPreTaskCode() <= 0 || codes.contains(r.getPreTaskCode()))
        .filter(r -> r.getPostTaskCode() > 0 && codes.contains(r.getPostTaskCode()))
        .collect(Collectors.toList());
WorkflowGraph g = new WorkflowGraph(taskDefinitions, valid); // fix orphaned rows in DB too
Defensive patterns

Strategy: validation

Validate before calling

Set<Long> codes = taskDefinitions.stream().map(TaskDefinition::getCode).collect(Collectors.toSet());
List<WorkflowTaskRelation> broken = relations.stream()
        .filter(r -> r.getPreTaskCode() > 0 && !codes.contains(r.getPreTaskCode()))
        .collect(Collectors.toList());
if (!broken.isEmpty()) throw new IllegalStateException("Dangling pre-task codes: " + broken);

Try / catch

try {
    WorkflowGraph graph = new WorkflowGraph(taskDefinitions, relations);
} catch (IllegalArgumentException e) {
    log.error("Workflow relations reference missing tasks: {}", e.getMessage());
    throw new WorkflowDefinitionCorruptException(e);
}

Prevention

When it happens

Trigger: Constructing WorkflowGraph with workflowTaskRelations whose getPreTaskCode() is > 0 but not present among the passed task definitions' codes.

Common situations: Relations referencing a task definition deleted from the workflow (orphaned edges in t_ds_workflow_task_relation); partial task list passed while the full relation set is used; task definition failed to save but relation did.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/5337ad7c5980b0ef. Report an issue: GitHub.