flowable/flowable-engine · error · FlowableIllegalArgumentException
Set of process instance ids is empty
Error message
Set of process instance ids is empty
What it means
HistoricActivityInstanceQueryImpl.processInstanceIds(Set<String>) also rejects an empty set with FlowableIllegalArgumentException. An empty set would translate to an impossible SQL IN () clause, so Flowable fails fast during query construction.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricActivityInstanceQueryImpl.java:98
@Override
public List<HistoricActivityInstance> executeList(CommandContext commandContext) {
return CommandContextUtil.getHistoricActivityInstanceEntityManager(commandContext).findHistoricActivityInstancesByQueryCriteria(this);
}
@Override
public HistoricActivityInstanceQueryImpl processInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl 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");
}
this.processInstanceIds = processInstanceIds;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl executionId(String executionId) {
this.executionId = executionId;
return this;
}
@Override
public HistoricActivityInstanceQueryImpl processDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
return this;
}
@OverrideView on GitHub (pinned to d6d39ce1c6)
Solutions
- Check !ids.isEmpty() before calling processInstanceIds; skip the filter or short-circuit to an empty result
- Return an empty result early in application code when no ids were selected, avoiding the DB query entirely
- Default to a non-filtering query when the set is empty, if 'all instances' is the intended meaning
Example fix
// before
Set<String> ids = selectedIds.stream().filter(this::valid).collect(toSet());
query.processInstanceIds(ids);
// after
Set<String> ids = selectedIds.stream().filter(this::valid).collect(toSet());
if (!ids.isEmpty()) {
query.processInstanceIds(ids);
} else {
return Collections.emptyList();
} Defensive patterns
Strategy: validation
Validate before calling
if (ids != null && !ids.isEmpty()) {
query.processInstanceIds(ids);
} else {
return Collections.emptyList();
} Type guard
boolean isNonEmptySet(Set<String> s) { return s != null && !s.isEmpty(); } Try / catch
try {
query.processInstanceIds(ids);
} catch (FlowableIllegalArgumentException e) {
if (!e.getMessage().contains("Set of process instance ids is empty")) throw e;
// short-circuit: no ids selected means no results
} Prevention
- Short-circuit to an empty result when the selection is empty
- Filter ids before building the query and branch on the resulting size
When it happens
Trigger: Calling processInstanceIds(new HashSet<>()) or a set filtered down to zero elements (e.g. user selected no instances, or all ids were filtered out before the call).
Common situations: UI-driven reports where the user deselects all items; batch jobs whose id list is empty because no instances matched a prior step.
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 called process instance ids is empty
- groupIds are empty
- Set of process instance ids is null
- Set of called process instance ids is null
- processInstanceIds is empty
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f8e9663ffe03a5d7.
Report an issue: GitHub.