flowable/flowable-engine · error · ActivitiIllegalArgumentException

Candidate group list is null

Error message

Candidate group list is null

What it means

TaskQueryImpl.taskCandidateGroupIn(List<String>) throws ActivitiIllegalArgumentException when the candidateGroups list is null. The Flowable/Activiti query API validates its arguments eagerly at query-build time so invalid queries fail immediately instead of producing confusing errors at list().call(). A null list carries no group filter, so it is rejected outright rather than silently ignored.

Solutions

  1. Ensure the list passed to taskCandidateGroupIn is non-null before building the query (initialize with Collections.emptyList() at the declaration site).
  2. If groups are optional, branch: skip calling taskCandidateGroupIn entirely when the list is null instead of passing null.
  3. Catch ActivitiIllegalArgumentException around the query construction to surface a user-facing message with the offending filter.

Example fix

// before
List<String> groups = loadGroups(userId);
taskQuery.taskCandidateGroupIn(groups);

// after
List<String> groups = loadGroups(userId);
if (groups != null && !groups.isEmpty()) {
    taskQuery.taskCandidateGroupIn(groups);
}
Defensive patterns

Strategy: validation

Validate before calling

if (candidateGroups == null) throw new IllegalArgumentException("candidateGroups must not be null");
taskQuery.taskCandidateGroupIn(candidateGroups);

Type guard

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

Try / catch

try {
    taskQuery.taskCandidateGroupIn(groups).list();
} catch (ActivitiIllegalArgumentException e) {
    log.warn("Invalid candidate group filter: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling taskQuery.taskCandidateGroupIn(null), typically when the group list comes from a variable, config property, or upstream lookup that returned null.

Common situations: Building a dynamic task query where the candidate groups are loaded from a database, LDAP sync result, or optional request parameter that resolved to null; forgetting to default an uninitialized collection before querying.

Related errors


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

Appendix: source

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

        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) {
        if (candidateGroups == null) {
            throw new ActivitiIllegalArgumentException("Candidate group list is null");
        }

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

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

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

View on GitHub (pinned to d6d39ce1c6)