flowable/flowable-engine · error · ActivitiIllegalArgumentException
Invalid query usage: cannot set both candidateGroup and…
Error message
Invalid query usage: cannot set both candidateGroup and candidateGroupIn
What it means
taskCandidateGroup(String candidateGroup) throws this error when candidateGroups (the list set via taskCandidateGroupIn) is already populated. A single candidate group and a candidate-group list are mutually exclusive filters; both would produce conflicting identity-link conditions. Remove one of the two calls.
Solutions
- Use taskCandidateGroupIn(list) exclusively, with the single group wrapped in a one-element list
- Rebuild the query instead of reusing a partially configured TaskQueryImpl
- Centralize candidate-group filtering in one helper that picks either single or list mode
Example fix
// before
query.taskCandidateGroupIn(groupList);
query.taskCandidateGroup("hr"); // throws
// after
List<String> groups = new ArrayList<>(groupList);
groups.add("hr");
query.taskCandidateGroupIn(groups); Defensive patterns
Strategy: validation
Validate before calling
if (singleGroup != null && groupList != null) {
throw new IllegalStateException("Use either taskCandidateGroup or taskCandidateGroupIn, not both");
} Try / catch
try {
query.taskCandidateGroup(singleGroup);
} catch (ActivitiIllegalArgumentException e) {
log.warn("Candidate group filters conflict: {}", e.getMessage());
query = taskService.createTaskQuery().taskCandidateGroupIn(groupList);
} Prevention
- Normalize all group filters to taskCandidateGroupIn with a list, wrapping single values
- Never reuse a partially configured TaskQuery object; create a fresh query per request
- Pick a single candidate-group filtering strategy in your query-building layer
When it happens
Trigger: Calling taskQuery.taskCandidateGroup("hr") after taskQuery.taskCandidateGroupIn(list) on the same query object (or same OR block). The check compares against the candidateGroups field at TaskQueryImpl.java:518.
Common situations: Composing queries from layered services that each add their own group filter; migrating from a single group to a group list while keeping the old call; generic search forms that support both modes without resetting the query.
Related errors
- Invalid query usage: cannot set candidateGroup
- Candidate group is null
- Invalid query usage: cannot set both candidateGroupIn and…
- Invalid query usage: cannot set both candidateGroup and…
- Invalid query usage: cannot set both candidateGroupIn and…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/0c610e55acffd116.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/TaskQueryImpl.java:518
if (involvedUser == null) {
throw new ActivitiIllegalArgumentException("Involved user is null");
}
if (orActive) {
currentOrQueryObject.involvedUser = involvedUser;
} else {
this.involvedUser = involvedUser;
}
return this;
}
@Override
public TaskQueryImpl taskCandidateGroup(String candidateGroup) {
if (candidateGroup == null) {
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");
}View on GitHub (pinned to d6d39ce1c6)