apache/dolphinscheduler · error · ServiceException
WORKFLOW_DAG_IS_EMPTY
WORKFLOW_DAG_IS_EMPTY
Error message
WORKFLOW_DAG_IS_EMPTY: workflow dag is empty
What it means
Thrown by checkWorkflowJsonValidation (WorkflowDefinitionServiceImpl) when transforming the workflow's task relation/definition JSON into TaskNode list yields zero task nodes. DolphinScheduler requires every saved workflow to contain at least one task node so a valid DAG can be built. Saving or validating a workflow whose 'tasks'/'taskDefinitions' JSON is empty triggers this error.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:949
* @return check result code
*/
@Override
public void checkWorkflowNodeList(String workflowTaskRelationJson,
List<TaskDefinitionLog> taskDefinitionLogsList) {
try {
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) {View on GitHub (pinned to 02eac45a1b)
Solutions
- Add at least one task node to the workflow definition JSON before saving (populate taskDefinitions and the corresponding taskRelations).
- Validate the workflow JSON with JSONUtils or the UI designer before submitting the create/update API call.
- Check that taskDefinitionJson entries parse correctly (correct field names/types) so transformTask does not silently produce an empty node list.
- If importing, re-export the workflow from a healthy environment and verify the tasks section is non-empty.
Example fix
// before
String json = "{\"globalParams\":[],\"tasks\":[]}";
workflowDefinitionService.createWorkflowDefinition(user, projectCode, name, json, ...);
// after
String json = "{\"globalParams\":[],\"tasks\":[{\"name\":\"shell_task\",\"taskType\":\"SHELL\",...}]}";
workflowDefinitionService.createWorkflowDefinition(user, projectCode, name, json, ...); Defensive patterns
Strategy: validation
Validate before calling
WorkflowTaskRelationList relations = JSONUtils.toList(taskRelationJson, WorkflowTaskRelation.class);
if (relations == null || relations.isEmpty() || taskDefinitionJsonList.isEmpty()) {
throw new IllegalArgumentException("workflow must contain at least one task");
} Type guard
boolean hasTasks(String workflowJson) {
List<TaskDefinitionLog> tasks = JSONUtils.toList(
JSONUtils.getNodeString(workflowJson, "taskDefinitionJson"), TaskDefinitionLog.class);
return tasks != null && !tasks.isEmpty();
} Try / catch
try {
saveWorkflow(json);
} catch (ServiceException e) {
if (e.getCode() == Status.WORKFLOW_DAG_IS_EMPTY.getCode()) {
// surface 'workflow must have at least one task' to the user
} else throw e;
} Prevention
- Always build workflows through the UI designer or an export/import round-trip, never empty task arrays
- Validate the JSON schema client-side before each save
- Add an integration test that round-trips create+query for every generated workflow
When it happens
Trigger: Calling createWorkflowDefinition/updateWorkflowDefinition (or importWorkflow) with a taskRelationJson/taskDefinitionJson that decodes to an empty list, e.g. workflowJson with no task objects, or JSON that fails to map into WorkflowTaskRelation/TaskDefinitionLog entries.
Common situations: Hand-editing workflow JSON and deleting all tasks; importing an exported workflow that lost its task list; programmatic API calls that build an empty task array; corrupted UI-generated JSON.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/f04108f10de4e2c6.
Report an issue: GitHub.