flowable/flowable-engine · error · FlowableIllegalArgumentException

Invalid query usage: cannot set both candidateGroupIn and…

Error message

Invalid query usage: cannot set both candidateGroupIn and candidateGroup

What it means

TaskQueryImpl.taskCandidateGroupIn() throws this when taskCandidateGroup() has already been called (candidateGroup != null). The single-group and group-list filters are mutually exclusive; setting both makes the query ambiguous. Flowable fails fast with FlowableIllegalArgumentException instead of emitting conflicting SQL.

Solutions

  1. Pick one filter: taskCandidateGroup() for a single group or taskCandidateGroupIn() for a list.
  2. Use taskCandidateGroupIn(Collections.singletonList(group)) when the input may be single or multiple.
  3. Instantiate a new TaskQuery per use instead of reusing cached instances.
  4. Refactor the query-composition code so the two filter branches are exclusive.

Example fix

// before
query.taskCandidateGroup("management");
query.taskCandidateGroupIn(groups);
// after
if (groups != null && !groups.isEmpty()) {
    query.taskCandidateGroupIn(groups);
} else {
    query.taskCandidateGroup("management");
}
Defensive patterns

Strategy: validation

Validate before calling

if (useSingleGroup) {
    query.taskCandidateGroup(group);
} else if (groups != null && !groups.isEmpty()) {
    query.taskCandidateGroupIn(groups);
}

Try / catch

try {
    query.taskCandidateGroupIn(groups);
} catch (FlowableIllegalArgumentException e) {
    logger.warn("candidateGroup already set: {}", e.getMessage());
    query = taskService.createTaskQuery();
}

Prevention

When it happens

Trigger: Calling taskCandidateGroupIn(list) after taskCandidateGroup("g") on the same query, including reused query instances or query builders that apply both filters.

Common situations: Merging two query-building features (single group vs multi-group); a TaskQuery field reused across requests keeping prior state; dynamic builders that always call both setters.

Related errors


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

Appendix: source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/TaskQueryImpl.java:668

            this.bothCandidateAndAssigned = true;
            this.userIdForCandidateAndAssignee = userIdForCandidateAndAssignee;
        }

        return this;
    }

    @Override
    public TaskQuery taskCandidateGroupIn(Collection<String> candidateGroups) {
        if (candidateGroups == null) {
            throw new FlowableIllegalArgumentException("Candidate group list is null");
        }

        if (candidateGroups.isEmpty()) {
            throw new FlowableIllegalArgumentException("Candidate group list is empty");
        }

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

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

    @Override
    public TaskQuery ignoreAssigneeValue() {
        if (orActive) {
            currentOrQueryObject.ignoreAssigneeValue = true;
        } else {
            this.ignoreAssigneeValue = true;
        }
        return this;

View on GitHub (pinned to d6d39ce1c6)