flowable/flowable-engine · error · ActivitiIllegalArgumentException
Set of process instance ids is empty
Error message
Set of process instance ids is empty
What it means
HistoricProcessInstanceQuery.processInstanceIds(Set<String>) also rejects an empty set with ActivitiIllegalArgumentException, because an empty IN-clause would match nothing and usually indicates a caller bug rather than an intentional filter. You must supply at least one process instance id.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricProcessInstanceQueryImpl.java:110
}
@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 ActivitiIllegalArgumentException("Set of process instance ids is null");
}
if (processInstanceIds.isEmpty()) {
throw new ActivitiIllegalArgumentException("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
- Only call processInstanceIds when the set has at least one element; otherwise skip the filter or return an empty result directly.
- Validate inputs before the call: if (ids == null || ids.isEmpty()) handle explicitly.
- Fix the id-collection step so it either produces real ids or signals 'nothing to do'.
- In batch flows, short-circuit the query when the id set is empty.
Example fix
// before
Set<String> ids = findCandidateIds(); // may be empty
query.processInstanceIds(ids);
List<HistoricProcessInstance> r = query.list();
// after
Set<String> ids = findCandidateIds();
List<HistoricProcessInstance> r = ids.isEmpty()
? Collections.emptyList()
: historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); Defensive patterns
Strategy: validation
Validate before calling
if (ids == null || ids.isEmpty()) {
return Collections.emptyList(); // nothing to look up
}
query.processInstanceIds(ids); Type guard
boolean hasIds(java.util.Collection<?> c) { return c != null && !c.isEmpty(); } Try / catch
try {
query.processInstanceIds(ids);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("is empty")) {
// treat as empty result or fix id collection step
}
} Prevention
- Short-circuit queries when the id set is empty.
- Don't forward raw upstream collections into IN-clause filters.
- Log/monitor empty id sets in batch jobs to catch producer bugs.
- Distinguish 'no input' (skip) from 'no results' (empty response).
When it happens
Trigger: Calling processInstanceIds(new HashSet<>()) or passing a set that was emptied by prior filtering — e.g. ids collected from a search that returned zero matches.
Common situations: Batch job with no work items after filtering; UI passing through an empty selection; upstream query returning no rows and the empty collection being forwarded unchanged.
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
- Set of process instance ids is empty
- groupIds are empty
- Set of process instance ids is empty
- Set of called process instance ids is empty
- Deployment id is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/0749bf8355500a38.
Report an issue: GitHub.