Activiti/Activiti · error · ActivitiIllegalArgumentException

Invalid query usage: cannot set both taskAssigneeIds and…

Error message

Invalid query usage: cannot set both taskAssigneeIds and taskAssigneeLike

What it means

This ActivitiIllegalArgumentException is thrown by TaskQueryImpl.taskAssigneeIds(List) when a task assignee-like filter was already set on the same query object. The task query API forbids combining assigneeIds with assignee/assigneeLike/assigneeLikeIgnoreCase because they target different DB column predicates and would produce an ambiguous SQL query. The library throws eagerly at query-build time to fail fast instead of generating broken SQL.

Solutions

  1. Remove the taskAssigneeLike(...) call from the query when using taskAssigneeIds(...)
  2. Pick one filter style: use assigneeIds for exact-id list matching, or assigneeLike/assigneeLikeIgnoreCase for pattern matching, not both
  3. If both filters are genuinely needed, run two queries and merge results in application code
  4. Guard conditional builder code so only one assignee-filter branch executes

Example fix

// before
List<Task> tasks = taskService.createTaskQuery()
    .taskAssigneeLike("kermit%")
    .taskAssigneeIds(ids)
    .list();
// after
List<Task> tasks = taskService.createTaskQuery()
    .taskAssigneeIds(ids)
    .list();
Defensive patterns

Strategy: validation

Validate before calling

if (assigneeIds != null && (assigneeLike != null || assigneeLikeIgnoreCase != null || assignee != null)) {
    throw new IllegalArgumentException("Use either taskAssigneeIds or a single assignee pattern filter, not both");
}
taskService.createTaskQuery().taskAssigneeIds(assigneeIds);

Type guard

boolean canUseAssigneeIds(TaskQueryImpl q) {
    return q.getAssignee() == null && q.getAssigneeLike() == null && q.getAssigneeLikeIgnoreCase() == null;
}

Try / catch

try {
    tasks = taskService.createTaskQuery().taskAssigneeIds(ids).list();
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("taskAssigneeIds")) {
        tasks = taskService.createTaskQuery().taskAssigneeLike(pattern).list();
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling taskQuery.taskAssigneeLike("kermit%").taskAssigneeIds(ids) (or the reverse order) on the same TaskQueryImpl instance, including inside an or() block where the same or-query object already holds assigneeLike.

Common situations: Building a dynamic task query where optional filters are applied conditionally and two branches both fired; migrating code from assigneeLike to the newer assigneeIds API and leaving the old call in place; copy-pasting query builder chains that mix assignee filter styles.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/ba542b87127cf095. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java:395

        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 (assignee != null) {
            throw new ActivitiIllegalArgumentException(
                "Invalid query usage: cannot set both taskAssigneeIds and taskAssignee"
            );
        }
        if (assigneeLike != null) {
            throw new ActivitiIllegalArgumentException(
                "Invalid query usage: cannot set both taskAssigneeIds and taskAssigneeLike"
            );
        }
        if (assigneeLikeIgnoreCase != null) {
            throw new ActivitiIllegalArgumentException(
                "Invalid query usage: cannot set both taskAssigneeIds and taskAssigneeLikeIgnoreCase"
            );
        }

        if (orActive) {
            currentOrQueryObject.assigneeIds = assigneeIds;
        } else {
            this.assigneeIds = assigneeIds;
        }
        return this;
    }

    public TaskQueryImpl taskOwner(String owner) {

View on GitHub (pinned to 56435b1a97)