flowable/flowable-engine · error · ActivitiIllegalArgumentException
Set of process instance ids is empty
Error message
Set of process instance ids is empty
What it means
processInstanceIds(Set) additionally throws ActivitiIllegalArgumentException('Set of process instance ids is empty') when the provided set has no elements, because an IN () clause is invalid and would silently match nothing.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/ProcessInstanceQueryImpl.java:115
public ProcessInstanceQueryImpl processInstanceId(String processInstanceId) {
if (processInstanceId == null) {
throw new ActivitiIllegalArgumentException("Process instance id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.executionId = processInstanceId;
} else {
this.executionId = processInstanceId;
}
return this;
}
@Override
public ProcessInstanceQuery 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 ProcessInstanceQuery processInstanceBusinessKey(String businessKey) {
if (businessKey == null) {
throw new ActivitiIllegalArgumentException("Business key is null");
}
if (inOrStatement) {
this.currentOrQueryObject.businessKey = businessKey;
} else {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Short-circuit: if the set is empty, return an empty result without executing the query
- Ensure upstream collection logic always leaves at least one id, or handle the empty case explicitly
- Use processInstanceId() for the single-id case after confirming size()==1 if appropriate
- Catch ActivitiIllegalArgumentException and treat it as 'no matches'
Example fix
// before
runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
// after
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); Defensive patterns
Strategy: validation
Validate before calling
if (ids == null || ids.isEmpty()) {
return Collections.emptyList(); // skip query entirely
}
query.processInstanceIds(ids); Type guard
boolean isNonEmptyCollection(Collection<String> c) { return c != null && !c.isEmpty(); } Try / catch
try {
query.processInstanceIds(ids);
} catch (ActivitiIllegalArgumentException e) {
return Collections.emptyList(); // treat empty as no matches
} Prevention
- Guard all IN-style query inputs for emptiness before execution
- Handle permission-intersection results that can legitimately be empty
- Prefer skipping the engine call over issuing an invalid query
When it happens
Trigger: Calling ProcessInstanceQuery.processInstanceIds(new HashSet<>()) or passing a set that was emptied by upstream filtering (e.g. intersection of permissions produced zero ids).
Common situations: Filter UIs where the user deselects all ids; permission-intersection code that legitimately yields an empty set but still issues the query.
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
- process definition tenantId is null
- Empty appsDefinitionIds
- groupIds are empty
- category is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8693fae05441c9f6.
Report an issue: GitHub.