flowable/flowable-engine · error · ActivitiIllegalArgumentException

Task assignee list is empty

Error message

Task assignee list is empty

What it means

HistoricTaskInstanceQueryImpl.taskAssigneeIds(List<String>) validates its input before storing it. Passing an empty (non-null) assigneeIds list makes the query filter meaningless, so the engine throws ActivitiIllegalArgumentException instead of returning an empty result set. This is eager fail-fast input validation on the query builder.

Solutions

  1. Check !assigneeIds.isEmpty() before calling taskAssigneeIds and skip the assignee filter (or fall back to an unfiltered query) when empty.
  2. If the empty list means 'no filter intended', omit the taskAssigneeIds(...) call entirely rather than passing an empty list.
  3. If the empty list is a genuine error in your domain, fail earlier with a clearer application-level message naming the missing selection.

Example fix

// before
List<String> ids = selectedAssignees();
query.taskAssigneeIds(ids);

// after
List<String> ids = selectedAssignees();
if (ids != null && !ids.isEmpty()) {
    query.taskAssigneeIds(ids);
}
Defensive patterns

Strategy: validation

Validate before calling

// Java
if (assigneeIds == null || assigneeIds.isEmpty()) {
    // skip filter or handle explicitly before calling
}

Try / catch

try {
    query.taskAssigneeIds(ids);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
    // fall back to unfiltered query or report invalid input
}

Prevention

When it happens

Trigger: Calling taskAssigneeIds(Collections.emptyList()) or taskAssigneeIds(new ArrayList<>()) on a HistoricTaskInstanceQuery (or via the or() block) with a list that has size 0.

Common situations: Building the list dynamically from user-selected assignees and calling the query even when nothing was selected; passing a config-driven list that defaults to empty; copying a pattern from taskAssignee(single value) without guarding the list size.

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 flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/4a63aa3e0988c597. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java:556

    }

    @Override
    public HistoricTaskInstanceQuery taskAssigneeLikeIgnoreCase(String taskAssigneeLikeIgnoreCase) {
        if (inOrStatement) {
            this.currentOrQueryObject.taskAssigneeLikeIgnoreCase = taskAssigneeLikeIgnoreCase.toLowerCase();
        } else {
            this.taskAssigneeLikeIgnoreCase = taskAssigneeLikeIgnoreCase.toLowerCase();
        }
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery taskAssigneeIds(List<String> assigneeIds) {
        if (assigneeIds == null) {
            throw new ActivitiIllegalArgumentException("Task assignee list is null");
        }
        if (assigneeIds.isEmpty()) {
            throw new ActivitiIllegalArgumentException("Task assignee list is empty");
        }
        for (String assignee : assigneeIds) {
            if (assignee == null) {
                throw new ActivitiIllegalArgumentException("None of the given task assignees can be null");
            }
        }

        if (taskAssignee != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both taskAssigneeIds and taskAssignee");
        }
        if (taskAssigneeLike != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both taskAssigneeIds and taskAssigneeLike");
        }
        if (taskAssigneeLikeIgnoreCase != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both taskAssigneeIds and taskAssigneeLikeIgnoreCase");
        }

        if (inOrStatement) {

View on GitHub (pinned to d6d39ce1c6)