apache/dolphinscheduler · error · ServiceException
WORKFLOW_NODE_HAS_CYCLE
WORKFLOW_NODE_HAS_CYCLE
Error message
WORKFLOW_NODE_HAS_CYCLE: workflow node has cycle
What it means
Thrown by checkWorkflowJsonValidation when graphHasCycle(taskNodes) detects a dependency cycle among the workflow's task nodes. A valid workflow DAG must be acyclic; a cycle would make topological scheduling impossible. The error names the offending workflow implicitly via the request context.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:955
if (workflowTaskRelationJson == null) {
log.error("workflow task relation data is null.");
throw new ServiceException(Status.DATA_IS_NOT_VALID, "null");
}
List<WorkflowTaskRelation> taskRelationList =
JSONUtils.toList(workflowTaskRelationJson, WorkflowTaskRelation.class);
// Check whether the task node is normal
List<TaskNode> taskNodes = processService.transformTask(taskRelationList, taskDefinitionLogsList);
if (CollectionUtils.isEmpty(taskNodes)) {
log.error("Task node data is empty.");
throw new ServiceException(Status.WORKFLOW_DAG_IS_EMPTY);
}
// check has cycle
if (graphHasCycle(taskNodes)) {
log.error("workflow DAG has cycle.");
throw new ServiceException(Status.WORKFLOW_NODE_HAS_CYCLE);
}
// check whether the workflow definition json is normal
for (TaskNode taskNode : taskNodes) {
if (!checkTaskParameters(taskNode.getType(), taskNode.getParams())) {
throw new ServiceException(Status.WORKFLOW_NODE_S_PARAMETER_INVALID, taskNode.getName());
}
// check extra params
CheckUtils.checkOtherParams(taskNode.getExtras());
}
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error(Status.INTERNAL_SERVER_ERROR_ARGS.getMsg(), e);
throw new ServiceException(Status.INTERNAL_SERVER_ERROR_ARGS, e.getMessage());
}
}View on GitHub (pinned to 02eac45a1b)
Solutions
- Inspect each task's preTasks/postTasks in the workflow JSON and remove the dependency edge that closes the cycle.
- Redraw the workflow in the UI designer, which prevents connecting tasks in a cycle, and re-save.
- Write a client-side topological sort (Kahn's algorithm) check over taskRelations before calling the API.
- If imported, fix the source export and re-import.
Example fix
// before (cycle)
taskA.setPreTasks(Lists.newArrayList("taskB"));
taskB.setPreTasks(Lists.newArrayList("taskA"));
// after (acyclic)
taskA.setPreTasks(Collections.emptyList());
taskB.setPreTasks(Lists.newArrayList("taskA")); Defensive patterns
Strategy: validation
Validate before calling
// Kahn's algorithm guard before calling the API
Map<String, List<String>> adj = buildAdjacency(taskRelations);
Deque<String> ready = nodesWithZeroIndegree(adj);
int removed = 0;
while (!ready.isEmpty()) { String n = ready.poll(); removed++; for (String m : adj.get(n)) if (--indeg(m) == 0) ready.add(m); }
if (removed < adj.size()) throw new IllegalStateException("workflow task relations contain a cycle"); Try / catch
try {
saveWorkflow(json);
} catch (ServiceException e) {
if (e.getCode() == Status.WORKFLOW_NODE_HAS_CYCLE.getCode()) {
log.error("cyclic preTask references in workflow {}", name);
} else throw e;
} Prevention
- Maintain preTasks references by task name/code generated from one source of truth
- Run a topological-sort check on any programmatically generated DAG before saving
- Avoid hand-editing taskRelationJson; regenerate it from task definitions
When it happens
Trigger: Saving/updating/importing a workflow where task A depends on B and B (transitively) depends on A — i.e. the preTaskNode/postTaskNode relations in taskRelationJson form a directed cycle.
Common situations: Hand-editing task relations and creating circular pre-task references; importing workflows modified externally; copy-paste mistakes in taskRelationJson postTaskNodeList values; programmatic DAG generation bugs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/88ec1b5a03a8d85d.
Report an issue: GitHub.