flowable/flowable-engine · error · FlowableIllegalArgumentException

Candidate group list is empty

Error message

Candidate group list is empty

What it means

taskCandidateGroupIn(Collection<String>) throws this error when the collection argument is non-null but has no elements. An empty IN-list would generate invalid or meaningless SQL, so Flowable rejects it eagerly.

Solutions

  1. Guard with !candidateGroups.isEmpty() before calling and skip the filter when empty.
  2. If 'no groups' should match nothing, return an empty result yourself without executing the query.
  3. If 'no groups' should match everything, build the query without any candidate-group criterion.

Example fix

// before
query.taskCandidateGroupIn(myGroups); // throws when myGroups is empty

// after
if (myGroups != null && !myGroups.isEmpty()) {
    query.taskCandidateGroupIn(myGroups);
}
Defensive patterns

Strategy: validation

Validate before calling

if (candidateGroups != null && !candidateGroups.isEmpty()) {
    historicTaskInstanceQuery.taskCandidateGroupIn(candidateGroups);
} else {
    // decide: either return an empty result or build the query without this filter
}

Type guard

boolean hasGroups(Collection<String> groups) {
    return groups != null && !groups.isEmpty();
}

Try / catch

try {
    query.taskCandidateGroupIn(candidateGroups);
} catch (FlowableIllegalArgumentException e) {
    // empty list: decide semantics — short-circuit to empty result or drop the filter
    return Collections.emptyList();
}

Prevention

When it happens

Trigger: Calling taskCandidateGroupIn(new ArrayList<>()) or taskCandidateGroupIn(Collections.emptyList()) — typically after filtering a group list down to zero elements, or when the user belongs to no groups.

Common situations: Filtering groups by permission/type and passing the (possibly empty) result; users with no group memberships; split of a blank comma-separated group string yielding an empty list.

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/df3a7c21d223dee2. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:1926

            throw new FlowableIllegalArgumentException("Invalid query usage: cannot set both candidateGroup and candidateGroupIn");
        }

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

    @Override
    public HistoricTaskInstanceQuery 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 (inOrStatement) {
            this.currentOrQueryObject.candidateGroups = candidateGroups;
        } else {
            this.candidateGroups = candidateGroups;
        }
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery taskInvolvedUser(String involvedUser) {
        if (involvedUser == null) {
            throw new FlowableIllegalArgumentException("involved user is null");

View on GitHub (pinned to d6d39ce1c6)