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
- Ensure at least one scope id is in the collection before calling scopeIds.
- Short-circuit: if the collection is null/empty, skip the query entirely and return an empty result.
- Guard with if (scopeIds != null && !scopeIds.isEmpty()) before building the query.
- 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
- Treat an empty id collection as an empty result, not a query input.
- Check collection size after any filtering/transformation that could empty it.
- Use scopeId(String) for the single-id case to avoid needless collection wrapping.
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
- Empty appsDefinitionIds
- Set of process instance ids is empty
- Could not find an app definition with id '<appDefinitionId>
- Could not find a deployment with id '<deploymentId>
- appsDefinitionIds is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/70f697b423681684.
Report an issue: GitHub.