flowable/flowable-engine · error · ActivitiIllegalArgumentException
Process instance id list is null
Error message
Process instance id list is null
What it means
HistoricTaskInstanceQueryImpl.processInstanceIdIn(List<String>) validates the list of process instance ids before building the query: it must be non-null and non-empty, and (as the surrounding code shows) no element may be null. The null-list case throws ActivitiIllegalArgumentException with 'Process instance id list is null'.
Solutions
- Initialize the list before calling, e.g. new ArrayList<>(ids).
- Guard the call: only apply the filter when the list is non-null and non-empty; otherwise skip it or short-circuit the search.
- Null-check every element too, since individual null ids are also rejected.
- Fix the producer that returns null lists so it returns empty collections instead.
Example fix
// before
List<String> ids = (List<String>) cache.get("pids"); // null
query.processInstanceIdIn(ids);
// after
List<String> ids = (List<String>) cache.get("pids");
if (ids != null && !ids.isEmpty()) {
query.processInstanceIdIn(ids);
} else {
return Collections.emptyList();
} Defensive patterns
Strategy: validation
Validate before calling
if (processInstanceIds == null || processInstanceIds.isEmpty()) {
return Collections.emptyList(); // or skip the filter
}
if (processInstanceIds.contains(null)) {
throw new IllegalArgumentException("null element in processInstanceIds");
} Type guard
boolean isUsableIdList(java.util.List<String> l) {
return l != null && !l.isEmpty() && l.stream().allMatch(java.util.Objects::nonNull);
} Try / catch
try {
query.processInstanceIdIn(ids);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("id list is null")) {
// treat as missing input: skip filter or fail with a domain error
}
} Prevention
- Guard producer methods to return empty lists, not null.
- Validate list and elements before applying IN filters.
- Short-circuit empty searches instead of issuing a doomed query.
- Null-check deserialized request bodies at the boundary.
When it happens
Trigger: Calling processInstanceIdIn(null) — usually a list that failed to load, an unguarded Optional.map chain, or a mapped request body missing the field.
Common situations: Job orchestrators forwarding id lists produced by an earlier step that returned nothing; REST payloads with an absent/incorrectly-named field deserialized to null; cache lookups that return null instead of an empty list.
Related errors
- Set of process instance ids is null
- activity tenant id is null
- Business key is null
- Deployment id is null
- deploymentCategory is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1b1f2f74801ffdc9.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java:162
.getHistoricTaskInstanceEntityManager()
.findHistoricTaskInstancesByQueryCriteria(this);
}
}
@Override
public HistoricTaskInstanceQueryImpl processInstanceId(String processInstanceId) {
if (inOrStatement) {
this.currentOrQueryObject.processInstanceId = processInstanceId;
} else {
this.processInstanceId = processInstanceId;
}
return this;
}
@Override
public HistoricTaskInstanceQueryImpl processInstanceIdIn(List<String> processInstanceIds) {
if (processInstanceIds == null) {
throw new ActivitiIllegalArgumentException("Process instance id list is null");
}
if (processInstanceIds.isEmpty()) {
throw new ActivitiIllegalArgumentException("Process instance id list is empty");
}
for (String processInstanceId : processInstanceIds) {
if (processInstanceId == null) {
throw new ActivitiIllegalArgumentException("None of the given process instance ids can be null");
}
}
if (inOrStatement) {
this.currentOrQueryObject.processInstanceIds = processInstanceIds;
} else {
this.processInstanceIds = processInstanceIds;
}
return this;
}
View on GitHub (pinned to d6d39ce1c6)