flowable/flowable-engine · error · FlowableIllegalArgumentException
Candidate group is null
Error message
Candidate group is null
What it means
HistoricTaskInstanceQueryImpl.taskCandidateGroup(String) throws FlowableIllegalArgumentException when the candidateGroup argument is null. Query setter methods in Flowable validate their required arguments immediately so invalid queries surface at call time. It also enforces that candidateGroup and candidateGroupIn are not both set.
Solutions
- Ensure a non-empty group id string is passed; check for null/emptiness before calling.
- Skip the taskCandidateGroup() call when no group filter is needed.
- If several groups may apply, use taskCandidateGroupIn(Collection) instead.
Example fix
// before
query.taskCandidateGroup(groupName);
// after
if (groupName != null) {
query.taskCandidateGroup(groupName);
} Defensive patterns
Strategy: validation
Validate before calling
if (candidateGroup == null || candidateGroup.isEmpty()) {
throw new IllegalArgumentException("candidateGroup must be a non-empty group id");
}
historicTaskInstanceQuery.taskCandidateGroup(candidateGroup); Type guard
boolean isValidGroup(String groupId) {
return groupId != null && !groupId.trim().isEmpty();
} Try / catch
try {
query.taskCandidateGroup(candidateGroup);
} catch (FlowableIllegalArgumentException e) {
log.warn("Invalid candidateGroup filter: {}", e.getMessage());
query = taskService.createHistoricTaskInstanceQuery(); // rebuild clean
} Prevention
- Validate group ids coming from configuration or request payloads before querying.
- Use taskCandidateGroupIn() when the number of groups may vary.
- Never chain taskCandidateGroup() and taskCandidateGroupIn() on the same query object.
When it happens
Trigger: Calling taskCandidateGroup(null) — usually a null group variable from an unassigned candidate group on the task definition, or an optional method/REST parameter forwarded without a check.
Common situations: Querying by a group that comes from task.getCandidateGroup() on tasks with no group candidate; config-driven filters where the group key was absent; dynamically built queries with optional group criteria.
Related errors
- Candidate group list is null
- Candidate user is null
- Involved groups are null
- involved user is null
- Assignee is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/48643c920f1451c8.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:1904
@Override
public HistoricTaskInstanceQuery taskCandidateUser(String candidateUser) {
if (candidateUser == null) {
throw new FlowableIllegalArgumentException("Candidate user is null");
}
if (inOrStatement) {
this.currentOrQueryObject.candidateUser = candidateUser;
} else {
this.candidateUser = candidateUser;
}
return this;
}
@Override
public HistoricTaskInstanceQuery taskCandidateGroup(String candidateGroup) {
if (candidateGroup == null) {
throw new FlowableIllegalArgumentException("Candidate group is null");
}
if (candidateGroups != null) {
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");View on GitHub (pinned to d6d39ce1c6)