flowable/flowable-engine · error · FlowableIllegalArgumentException

groupIds are null

Error message

groupIds are null

What it means

HistoricCaseInstanceQueryImpl.involvedGroups(Set<String>) throws FlowableIllegalArgumentException("groupIds are null") when the set of group ids is null. The set feeds an IN-clause over group identity links, so null input is rejected immediately.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java:1127

    public HistoricCaseInstanceQuery 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 HistoricCaseInstanceQuery involvedGroups(Set<String> groupIds) {
        if (groupIds == null) {
            throw new FlowableIllegalArgumentException("groupIds are null");
        }
        if (groupIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("groupIds are empty");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.involvedGroups = groupIds;
        } else {
            this.involvedGroups = groupIds;
        }
        return this;
    }

    @Override
    public HistoricCaseInstanceQuery or() {
        if (inOrStatement) {
            throw new FlowableException("the query is already in an or statement");
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a non-null Set of group ids; initialize empty collections rather than null.
  2. Only add the involvedGroups filter when the set exists; branch on membership results.
  3. Make membership-resolution helpers return an empty set and check isEmpty before filtering.
  4. Ensure config/claims-to-set conversion cannot return null.

Example fix

// before
query.involvedGroups(groupIds); // groupIds may be null
// after
if (groupIds != null && !groupIds.isEmpty()) {
    query.involvedGroups(groupIds);
}
Defensive patterns

Strategy: validation

Validate before calling

if (groupIds == null || groupIds.isEmpty()) {
    throw new IllegalArgumentException("groupIds must be non-empty");
}
query.involvedGroups(groupIds);

Type guard

boolean isNonEmpty(Set<String> s) {
    return s != null && !s.isEmpty();
}

Try / catch

try {
    query.involvedGroups(groupIds);
} catch (FlowableIllegalArgumentException e) {
    if ("groupIds are null".equals(e.getMessage())) {
        // skip filter or rethrow with context
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling involvedGroups(null) on a HistoricCaseInstanceQuery, inside or outside an or() block, before executing the query.

Common situations: Group memberships lookup returned null (e.g. user with no groups); a roles/claims mapper produced null instead of an empty set; generic query-builder code passing an unset parameter.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/7eb83649a72e0182. Report an issue: GitHub.