flowable/flowable-engine · error · FlowableIllegalArgumentException

Involved groups are empty

Error message

Involved groups are empty

What it means

ProcessInstanceQueryImpl.involvedGroups(Set<String>) requires a non-null, non-empty set of group IDs. Flowable throws FlowableIllegalArgumentException when an empty set is passed because an 'involved groups' filter matches nothing by definition, and an empty filter would silently produce an unusable or misleading query. The library fails fast instead of building a query with no filtering semantics.

Solutions

  1. Only call involvedGroups when the set has at least one element; skip the filter otherwise
  2. Pre-populate the set with the intended group IDs before building the query
  3. Fix upstream group/role resolution so it returns the actual group IDs rather than an empty collection
  4. Catch FlowableIllegalArgumentException and fall back to an unfiltered query if that is the desired behavior

Example fix

// before
query.involvedGroups(groupIds);
// after
if (groupIds != null && !groupIds.isEmpty()) {
    query.involvedGroups(groupIds);
} else {
    query = runtimeService.createProcessInstanceQuery(); // drop the filter
}
Defensive patterns

Strategy: validation

Validate before calling

if (groupIds == null || groupIds.isEmpty()) {
    throw new IllegalArgumentException("involvedGroups must contain at least one group id");
}

Type guard

boolean hasGroups = groupIds != null && !groupIds.isEmpty();

Try / catch

try {
    query.involvedGroups(groupIds);
} catch (FlowableIllegalArgumentException e) {
    query = runtimeService.createProcessInstanceQuery(); // proceed unfiltered or rethrow
}

Prevention

When it happens

Trigger: Calling processInstanceQuery.involvedGroups(new HashSet<>()) or involvedGroups(Collections.emptySet()), or passing a set built from an empty filter/selection UI. Passing null throws a sibling message 'Involved groups are null'.

Common situations: Building admin UIs where the user selected no groups but the code still applies the filter; building the set dynamically from role/tenant lookups that returned nothing; migrating code from another engine API that tolerated empty collections.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/ProcessInstanceQueryImpl.java:622

        }
        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 ProcessInstanceQuery involvedGroups(Set<String> involvedGroups) {
        if (involvedGroups == null) {
            throw new FlowableIllegalArgumentException("Involved groups are null");
        }
        if (involvedGroups.isEmpty()) {
            throw new FlowableIllegalArgumentException("Involved groups are empty");
        }

        if (inOrStatement) {
            this.currentOrQueryObject.involvedGroups = involvedGroups;
        } else {
            this.involvedGroups = involvedGroups;
        }
        return this;
    }

    @Override
    public ProcessInstanceQuery active() {
        if (inOrStatement) {
            this.currentOrQueryObject.suspensionState = SuspensionState.ACTIVE;
        } else {
            this.suspensionState = SuspensionState.ACTIVE;
        }
        return this;

View on GitHub (pinned to d6d39ce1c6)