flowable/flowable-engine · error · org.flowable.common.engine.api.FlowableIllegalArgumentException

scopeIds is empty

Error message

scopeIds is empty

What it means

HistoricVariableInstanceQuery.scopeIds() throws FlowableIllegalArgumentException when the scopeIds collection is null or empty. Querying by scope ids is only meaningful with at least one id, so an empty collection is rejected rather than producing an IN () SQL fragment that would fail or match nothing.

Source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/HistoricVariableInstanceQueryImpl.java:260

    @Override
    public HistoricVariableInstanceQuery variableNameLike(String variableNameLike) {
        if (variableNameLike == null) {
            throw new FlowableIllegalArgumentException("variableNameLike is null");
        }
        this.variableNameLike = variableNameLike;
        return this;
    }
    
    @Override
    public HistoricVariableInstanceQuery scopeId(String scopeId) {
        this.scopeId = scopeId;
        return this;
    }
    
    @Override
    public HistoricVariableInstanceQuery scopeIds(Collection<String> scopeIds) {
        if (scopeIds == null || scopeIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("scopeIds is empty");
        }
        this.scopeIds = scopeIds;
        return this;
    }

    @Override
    public HistoricVariableInstanceQuery subScopeId(String subScopeId) {
        if (excludeLocalVariables) {
            throw new FlowableIllegalArgumentException("Cannot use subScopeId together with excludeLocalVariables");
        }

        this.subScopeId = subScopeId;
        return this;
    }
    
    @Override
    public HistoricVariableInstanceQuery scopeType(String scopeType) {
        this.scopeType = scopeType;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure at least one scope id is in the collection before calling scopeIds.
  2. Short-circuit: if the collection is null/empty, skip the query entirely and return an empty result.
  3. Guard with if (scopeIds != null && !scopeIds.isEmpty()) before building the query.
  4. If you meant a single scope, use scopeId(String) instead of building a one-element collection incorrectly.

Example fix

// before
query.scopeIds(taskIds);

// after
if (taskIds != null && !taskIds.isEmpty()) {
    query.scopeIds(taskIds);
} else {
    return Collections.emptyList();
}
Defensive patterns

Strategy: validation

Validate before calling

if (scopeIds == null || scopeIds.isEmpty()) {
    return Collections.emptyList(); // nothing to query
}

Try / catch

try {
    query.scopeIds(scopeIds);
} catch (FlowableIllegalArgumentException e) {
    return Collections.emptyList();
}

Prevention

When it happens

Trigger: Calling historicVariableInstanceQuery.scopeIds(null) or scopeIds(Collections.emptyList()) / a list that ended up empty after filtering.

Common situations: Collecting task or execution ids into a list that turns out empty (e.g. a user with no tasks) and passing it directly; a batch job with nothing to process still invoking the query; null returned from an upstream lookup.

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/70f697b423681684. Report an issue: GitHub.