flowable/flowable-engine · error · FlowableIllegalArgumentException

rootScopeIds is null or empty

Error message

rootScopeIds is null or empty

What it means

caseInstanceRootScopeIds(Set<String>) throws 'rootScopeIds is null or empty' when the set is null or has no elements. Unlike most setters that only reject null, this one also rejects an empty set, so callers must supply at least one root scope id.

Source

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

    }
    
    @Override
    public HistoricCaseInstanceQueryImpl caseInstanceRootScopeId(String rootScopeId) {
        if (rootScopeId == null) {
            throw new FlowableIllegalArgumentException("rootScopeId is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.rootScopeId = rootScopeId;
        } else {
            this.rootScopeId = rootScopeId;
        }
        return this;
    }

    @Override
    public HistoricCaseInstanceQuery caseInstanceRootScopeIds(Set<String> rootScopeIds) {
        if (rootScopeIds == null || rootScopeIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("rootScopeIds is null or empty");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.rootScopeIds = rootScopeIds;
        } else {
            this.rootScopeIds = rootScopeIds;
        }
        return this;
    }

    @Override
    public HistoricCaseInstanceQueryImpl caseInstanceParentScopeId(String parentScopeId) {
        if (parentScopeId == null) {
            throw new FlowableIllegalArgumentException("parentScopeId is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.parentScopeId = parentScopeId;
        } else {
            this.parentScopeId = parentScopeId;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the set contains at least one id before calling.
  2. Skip the setter entirely (no root-scope filter) when the set is empty.
  3. Catch FlowableIllegalArgumentException and return a 'select at least one scope' validation message.

Example fix

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

Strategy: validation

Validate before calling

if (rootScopeIds == null || rootScopeIds.isEmpty()) { throw new IllegalArgumentException("rootScopeIds must contain at least one id"); }
historicCaseInstanceQuery.caseInstanceRootScopeIds(rootScopeIds);

Type guard

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

Try / catch

try {
    query.caseInstanceRootScopeIds(rootScopeIds);
} catch (FlowableIllegalArgumentException e) {
    throw new BadRequestException("At least one root scope id is required", e);
}

Prevention

When it happens

Trigger: Calling caseInstanceRootScopeIds(null) or caseInstanceRootScopeIds(new HashSet<>()) / an empty collection produced by filtering.

Common situations: Dynamic filter builders that collect selected root scopes from UI selections where nothing was selected; stream filters that removed all entries.

Related errors


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