flowable/flowable-engine · error · FlowableIllegalArgumentException
Set of process instance ids is empty
Error message
Set of process instance ids is empty
What it means
Flowable's HistoricProcessInstanceQuery.processInstanceIds(Set<String>) rejects empty sets. An empty id set would produce an impossible or unbounded SQL IN clause, so the API throws FlowableIllegalArgumentException at query-build time. Callers must supply at least one process instance id.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java:164
}
@Override
public HistoricProcessInstanceQueryImpl processInstanceId(String processInstanceId) {
if (inOrStatement) {
this.currentOrQueryObject.processInstanceId = processInstanceId;
} else {
this.processInstanceId = processInstanceId;
}
return this;
}
@Override
public HistoricProcessInstanceQuery processInstanceIds(Set<String> processInstanceIds) {
if (processInstanceIds == null) {
throw new FlowableIllegalArgumentException("Set of process instance ids is null");
}
if (processInstanceIds.isEmpty()) {
throw new FlowableIllegalArgumentException("Set of process instance ids is empty");
}
if (inOrStatement) {
this.currentOrQueryObject.processInstanceIds = processInstanceIds;
} else {
this.processInstanceIds = processInstanceIds;
}
return this;
}
@Override
public HistoricProcessInstanceQueryImpl processDefinitionId(String processDefinitionId) {
if (inOrStatement) {
this.currentOrQueryObject.processDefinitionId = processDefinitionId;
} else {
this.processDefinitionId = processDefinitionId;
}
return this;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Populate the set with at least one id before calling processInstanceIds
- Guard the call with !ids.isEmpty() and skip/alter the query when empty
- Decide on explicit behavior for the empty case: return no results early instead of executing the query
- Use a different query criterion entirely when no ids are known
Example fix
// before
query.processInstanceIds(ids); // throws when ids.isEmpty()
// after
if (ids != null && !ids.isEmpty()) {
query.processInstanceIds(ids);
} else {
return Collections.emptyList();
} Defensive patterns
Strategy: validation
Validate before calling
if (ids == null || ids.isEmpty()) {
return Collections.emptyList(); // nothing to query
}
query.processInstanceIds(ids); Type guard
boolean hasElements(Set<String> s) {
return s != null && !s.isEmpty();
} Try / catch
try {
query.processInstanceIds(ids);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().contains("empty")) {
return Collections.emptyList();
}
throw e;
} Prevention
- Check isEmpty() before building IN-style criteria
- Short-circuit to an empty result when no ids are known
- Add unit tests covering the empty-collection path
- Avoid returning freshly allocated empty sets from id-collection methods without callers checking
When it happens
Trigger: Calling processInstanceIds(ids) where ids is a non-null but empty Set — e.g. new HashSet<>() passed directly, or a filtered collection that ended up with zero elements.
Common situations: Filtering results upstream removed all entries before the query was built; initializing a set but never populating it; paging logic that produced an empty batch of ids.
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
- rootScopeIds is null or empty
- Set of process definition ids is empty
- Provided batch types must be provided and not empty
- Case definition version is null
- Case instance id is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/bb42cd450f873326.
Report an issue: GitHub.