flowable/flowable-engine · error · FlowableIllegalArgumentException
involvedGroups are null
Error message
involvedGroups are null
What it means
HistoricProcessInstanceQuery.involvedGroups(Set<String>) requires a non-null set of group ids. Flowable throws FlowableIllegalArgumentException when involvedGroups is null, preventing an undefined IN filter on group identity links. The check runs eagerly when building the query.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java:638
public HistoricProcessInstanceQuery involvedGroup(String groupId, String identityLinkType) {
if (groupId == null) {
throw new FlowableIllegalArgumentException("groupId is null");
}
if (identityLinkType == null) {
throw new FlowableIllegalArgumentException("identityLinkType is null");
}
if (inOrStatement) {
this.currentOrQueryObject.involvedGroupIdentityLink = new IdentityLinkQueryObject(null, groupId, identityLinkType);
} else {
this.involvedGroupIdentityLink = new IdentityLinkQueryObject(null, groupId, identityLinkType);
}
return this;
}
@Override
public HistoricProcessInstanceQuery involvedGroups(Set<String> involvedGroups) {
if (involvedGroups == null) {
throw new FlowableIllegalArgumentException("involvedGroups are null");
}
if (involvedGroups.isEmpty()) {
throw new FlowableIllegalArgumentException("involvedGroups are empty");
}
if (inOrStatement) {
this.currentOrQueryObject.involvedGroups = involvedGroups;
} else {
this.involvedGroups = involvedGroups;
}
return this;
}
@Override
public HistoricProcessInstanceQuery includeProcessVariables() {
this.includeProcessVariables = true;
return this;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Initialize the set before the call, e.g. Set<String> groups = new HashSet<>(...);
- Null-check and skip the criterion or fall back to another filter when null
- Use Collections.emptySet() semantics explicitly: only call involvedGroups when groups != null
- If the user has no groups, decide the intended result (no filter vs empty result) and code accordingly
Example fix
// before
query.involvedGroups(groups); // throws when groups == null
// after
if (groups != null && !groups.isEmpty()) {
query.involvedGroups(groups);
} Defensive patterns
Strategy: validation
Validate before calling
if (groups == null) {
throw new IllegalArgumentException("involvedGroups must be non-null");
}
if (!groups.isEmpty()) {
query.involvedGroups(groups);
} Type guard
boolean isValidGroupSet(Set<String> groups) {
return groups != null;
} Try / catch
try {
query.involvedGroups(groups);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().contains("null")) {
groups = Collections.emptySet(); // then decide on empty-set behavior
} else {
throw e;
}
} Prevention
- Initialize group collections eagerly rather than leaving fields null
- Return Collections.emptySet() from membership lookups instead of null
- Validate query-builder inputs in a single helper layer
- Distinguish 'no filter' from 'no groups' explicitly in your API design
When it happens
Trigger: Calling involvedGroups(groups) with a null set — e.g. the group set comes from a membership lookup returning null, an uninitialized field, or a nullable request parameter.
Common situations: Authorization-scoped history queries where user group resolution failed; bulk queries built from config that omitted the group list; refactors changing empty-set defaults to null.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f0f3136f0ad8d651.
Report an issue: GitHub.