apache/dolphinscheduler · error · ServiceException
20016
20016
Error message
resource not exist or no permission,please view the task node and remove error resource
What it means
TaskSubWorkflowPermissionChecker.checkPermission resolves the sub-workflow definition codes referenced by a task. If workflowDefinitionDao.queryByCodes returns null it throws ServiceException with Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION (20016). This is the 'no sub workflows found at all' branch.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java:79
if (!TaskTypeUtils.isSubWorkflowTask(taskDefinition.getTaskType())) {
continue;
}
SubWorkflowParameters subWorkflowParameters =
JSONUtils.parseObject(taskDefinition.getTaskParams(), SubWorkflowParameters.class);
if (subWorkflowParameters.getWorkflowDefinitionCode() > 0) {
subWorkflowDefinitionCodes.add(subWorkflowParameters.getWorkflowDefinitionCode());
}
}
if (subWorkflowDefinitionCodes.isEmpty()) {
return;
}
List<WorkflowDefinition> subWorkflowDefinitions =
workflowDefinitionDao.queryByCodes(subWorkflowDefinitionCodes);
if (subWorkflowDefinitions == null) {
log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
}
Set<Long> existingSubWorkflowDefinitionCodes =
subWorkflowDefinitions.stream().map(WorkflowDefinition::getCode).collect(Collectors.toSet());
if (!existingSubWorkflowDefinitionCodes.containsAll(subWorkflowDefinitionCodes)) {
log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
}
Set<Long> subWorkflowProjectCodes = subWorkflowDefinitions.stream()
.map(WorkflowDefinition::getProjectCode)
.collect(Collectors.toSet());
try {
for (Long projectCode : subWorkflowProjectCodes) {
projectService.checkHasProjectWritePermissionThrowException(loginUser, projectCode);
}
} catch (ServiceException ex) {
log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);View on GitHub (pinned to 02eac45a1b)
Solutions
- Open the task node and update/clear the sub-workflow reference to an existing workflow
- Recreate the deleted sub-workflow (or re-import it from the source environment)
- Check the referenced workflow codes against t_ds_workflow_definition
- Redeploy the parent workflow with valid resource references
Example fix
// before
List<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(codes);
if (defs == null) throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
// after: validate references up front
long existing = codes.stream().filter(c -> workflowDefinitionDao.findDefinitionByCode(c) != null).count();
if (existing != codes.size()) {
throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
} Defensive patterns
Strategy: validation
Validate before calling
// before saving a task referencing sub-workflows
for (Long code : subWorkflowDefinitionCodes) {
if (workflowDefinitionDao.findDefinitionByCode(code) == null) {
throw new ServiceException("sub workflow " + code + " does not exist");
}
} Type guard
boolean allSubWorkflowsExist(Set<Long> codes) {
List<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(new ArrayList<>(codes));
return defs != null && defs.stream().map(WorkflowDefinition::getCode)
.collect(Collectors.toSet()).containsAll(codes);
} Try / catch
try {
taskDefinitionService.updateTaskDefinition(...);
} catch (ServiceException e) {
if (e.getCode() == 20016) {
log.warn("referenced sub workflow missing - repair task node");
}
throw e;
} Prevention
- Check referenced workflows exist before cross-environment deployment
- Block deletion of workflows used as SUB_PROCESS targets
- Validate task JSON after imports/migrations
- Use UI pickers rather than manually typing workflow codes
When it happens
Trigger: A SUB_PROCESS/dependent task references sub-workflow codes that were deleted or never existed, so queryByCodes yields no rows (null).
Common situations: Sub-workflow deleted after the parent task was created; workflow imported/copied across environments where target workflows don't exist; code values corrupted by manual JSON editing.
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/f84f7cf77f0a721e.
Report an issue: GitHub.