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
- Ensure the list passed to taskCandidateGroupIn is non-null before building the query (initialize with Collections.emptyList() at the declaration site).
- If groups are optional, branch: skip calling taskCandidateGroupIn entirely when the list is null instead of passing null.
- 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
- Initialize collection fields with empty lists, never null
- Validate all query inputs in one place before building queries
- Treat optional filters as 'skip the call', not 'pass null'
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
- Candidate group list is empty
- None of the given process instance ids can be null
- Process category list is empty
- Process category list is null
- Process instance id list is empty
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)