flowable/flowable-engine · error · FlowableIllegalArgumentException

involvedGroups are null

Error message

involvedGroups are null

What it means

CaseInstanceQueryImpl.involvedGroups(Set<String>) throws FlowableIllegalArgumentException with message 'involvedGroups are null' when the group id set is null. Flowable requires an actual set to filter on; a null set cannot be distinguished from 'no filter' by the engine.

Solutions

  1. Pass an empty Set (Collections.emptySet()) instead of null when no group filter is intended, or skip the call entirely when null.
  2. Null-guard before the call: only apply involvedGroups when the set is non-null.
  3. Fix the producer (identity/tenant lookup) to return an empty collection rather than null.
  4. Add a DTO-level default so the groups field is always initialized to an empty set.

Example fix

// before
query.involvedGroups(filter.getGroupIds());
// after
if (filter.getGroupIds() != null && !filter.getGroupIds().isEmpty()) {
    query.involvedGroups(filter.getGroupIds());
}
Defensive patterns

Strategy: validation

Validate before calling

if (groupIds == null) {
    throw new IllegalArgumentException("groupIds must not be null; use an empty check to skip the filter");
}
query.involvedGroups(groupIds);

Type guard

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

Try / catch

try {
    query.involvedGroups(groupIds);
} catch (FlowableIllegalArgumentException e) {
    log.warn("involvedGroups filter invalid: {}", e.getMessage());
    // fall back to query without group filter
}

Prevention

When it happens

Trigger: Calling caseInstanceQuery().involvedGroups(null), e.g. when a group list field in a filter DTO was never initialized or a service returned null instead of an empty collection.

Common situations: Search services aggregating the user's groups from an identity provider that returned null on failure; deserialized request bodies missing the groups field.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java:857

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

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

View on GitHub (pinned to d6d39ce1c6)