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

  1. Add at least one task node to the workflow definition JSON before saving (populate taskDefinitions and the corresponding taskRelations).
  2. Validate the workflow JSON with JSONUtils or the UI designer before submitting the create/update API call.
  3. Check that taskDefinitionJson entries parse correctly (correct field names/types) so transformTask does not silently produce an empty node list.
  4. 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

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.