flowable/flowable-engine · error · FlowableIllegalArgumentException
groupId is null
Error message
groupId is null
What it means
HistoricProcessInstanceQuery.involvedGroup(String groupId, String identityLinkType) requires a non-null groupId. Flowable throws FlowableIllegalArgumentException when groupId is null, as an identity-link group filter without a group id is undefined. Validation is fail-fast at query-build time.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java:622
public HistoricProcessInstanceQuery involvedUser(String userId, String identityLinkType) {
if (userId == null) {
throw new FlowableIllegalArgumentException("userId is null");
}
if (identityLinkType == null) {
throw new FlowableIllegalArgumentException("identityLinkType is null");
}
if (inOrStatement) {
this.currentOrQueryObject.involvedUserIdentityLink = new IdentityLinkQueryObject(userId, null, identityLinkType);
} else {
this.involvedUserIdentityLink = new IdentityLinkQueryObject(userId, null, identityLinkType);
}
return this;
}
@Override
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()) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Pass a non-null groupId string to involvedGroup
- Null-check the group id first and skip the criterion or use an alternate query when absent
- Resolve the group from the authenticated user's memberships before building the query
- Use involvedGroups(Set) instead if multiple candidate groups exist
Example fix
// before
query.involvedGroup(groupId, IdentityLinkType.PARTICIPANT); // throws when groupId == null
// after
if (groupId != null) {
query.involvedGroup(groupId, IdentityLinkType.PARTICIPANT);
} Defensive patterns
Strategy: validation
Validate before calling
if (groupId == null) {
throw new IllegalArgumentException("groupId is required for involvedGroup filter");
}
query.involvedGroup(groupId, IdentityLinkType.PARTICIPANT); Type guard
boolean isValidGroupId(String groupId) {
return groupId != null && !groupId.trim().isEmpty();
} Try / catch
try {
query.involvedGroup(groupId, identityLinkType);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().equals("groupId is null")) {
// fall back to a query without the involvedGroup criterion
} else {
throw e;
}
} Prevention
- Resolve group memberships before building group-scoped queries
- Null-check group ids at the service boundary
- Return empty collections (not null) from membership lookups
- Make groupId a required parameter in wrapper APIs
When it happens
Trigger: Calling involvedGroup(null, identityLinkType) — e.g. group id resolved from user membership lookup that returned null, or a nullable request parameter.
Common situations: Multi-tenant/authorization filtering where the caller's group is unknown; group synchronization jobs that haven't run; forwarding optional group parameters from controllers.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4a491b55ede494b7.
Report an issue: GitHub.