flowable/flowable-engine · error · ActivitiIllegalArgumentException

Invalid query usage: cannot set candidateGroup

Error message

Invalid query usage: cannot set candidateGroup

What it means

taskCandidateOrAssigned(String userIdForCandidateAndAssignee) throws this error when a candidateGroup filter has already been set on the query. The candidate-or-assigned lookup resolves tasks by candidate user OR assignee, which is incompatible with a candidate-group-only filter in the same query. Remove the taskCandidateGroup call or use separate queries.

Solutions

  1. Drop taskCandidateGroup when using taskCandidateOrAssigned; the method already covers the user's candidate and assignee view
  2. Run two queries (one group-based, one candidate-or-assigned) and merge results
  3. Refactor the query builder so group and user filtering modes are chosen once, up front

Example fix

// before
query.taskCandidateGroup("hr");
query.taskCandidateOrAssigned("kermit"); // throws
// after
query.taskCandidateOrAssigned("kermit");
Defensive patterns

Strategy: validation

Validate before calling

if (candidateGroup != null && candidateOrAssignedUser != null) {
    throw new IllegalStateException("taskCandidateOrAssigned cannot be combined with taskCandidateGroup");
}

Try / catch

try {
    query.taskCandidateOrAssigned(userId);
} catch (ActivitiIllegalArgumentException e) {
    log.warn("candidateGroup already set: {}", e.getMessage());
    query = taskService.createTaskQuery().taskCandidateGroup(candidateGroup);
}

Prevention

When it happens

Trigger: Calling taskQuery.taskCandidateOrAssigned(userId) after taskQuery.taskCandidateGroup(...) (or a prior candidateGroup set in the same OR block) - checked at TaskQueryImpl.java:532.

Common situations: Shared task-list code that always adds a group filter, then product code adds candidate-or-assigned for personal tasks; OR queries where blocks accumulated conflicting filters; migration from group-based to user-based task assignment.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/7d73eb237530e11b. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java:532

            throw new ActivitiIllegalArgumentException("Candidate group is null");
        }

        if (candidateGroups != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both candidateGroup and candidateGroupIn");
        }

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

    @Override
    public TaskQuery taskCandidateOrAssigned(String userIdForCandidateAndAssignee) {
        if (candidateGroup != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set candidateGroup");
        }
        if (candidateUser != null) {
            throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both candidateGroup and candidateUser");
        }

        if (orActive) {
            currentOrQueryObject.bothCandidateAndAssigned = true;
            currentOrQueryObject.userIdForCandidateAndAssignee = userIdForCandidateAndAssignee;
        } else {
            this.bothCandidateAndAssigned = true;
            this.userIdForCandidateAndAssignee = userIdForCandidateAndAssignee;
        }

        return this;
    }

    @Override
    public TaskQuery taskCandidateGroupIn(List<String> candidateGroups) {

View on GitHub (pinned to d6d39ce1c6)