flowable/flowable-engine · error · ActivitiIllegalArgumentException
Candidate group is null
Error message
Candidate group is null
What it means
HistoricTaskInstanceQueryImpl.taskCandidateGroup(String) rejects a null candidateGroup with ActivitiIllegalArgumentException. Like the other setters here it validates eagerly before mutating query state.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java:1081
@Override
public HistoricTaskInstanceQuery taskCandidateUser(String candidateUser) {
if (candidateUser == null) {
throw new ActivitiIllegalArgumentException("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 ActivitiIllegalArgumentException("Candidate group is null");
}
if (candidateGroups != null) {
throw new ActivitiIllegalArgumentException("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(List<String> candidateGroups) {
if (candidateGroups == null) {
throw new ActivitiIllegalArgumentException("Candidate group list is null");View on GitHub (pinned to d6d39ce1c6)
Solutions
- Guard with if (candidateGroup != null) before calling taskCandidateGroup and omit the filter otherwise.
- Resolve the group earlier and abort the query build with a domain-specific error if the group is mandatory.
- Use taskCandidateGroupIn(list) with a populated list if the filter may come from several groups.
Example fix
// before
String group = resolveGroup(tenantId);
query.taskCandidateGroup(group); // throws when unresolved
// after
String group = resolveGroup(tenantId);
if (group != null) {
query.taskCandidateGroup(group);
} Defensive patterns
Strategy: validation
Validate before calling
// Java
if (candidateGroup != null && !candidateGroup.isEmpty()) {
query.taskCandidateGroup(candidateGroup);
} Try / catch
try {
query.taskCandidateGroup(group);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
logger.warn("No candidate group resolved; skipping group filter");
} Prevention
- Resolve group ids with a non-null default policy before query building.
- Log/skip rather than pass through unresolved group lookups.
- Consider taskCandidateGroupIn for multi-group scenarios.
When it happens
Trigger: Calling taskCandidateGroup(null), typically when the group id comes from an unset configuration value, request parameter, or lookup that returned null.
Common situations: Tenant/group resolution code that fails to resolve a group and still builds the query; optional group filter forwarded as null from an API layer.
Related errors
- Candidate user is null
- Candidate group list is null
- DeploymentId is null
- Error retrieving app engine info
- No deployment id available
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/621687ce01190041.
Report an issue: GitHub.