flowable/flowable-engine · error · ActivitiIllegalArgumentException
Set of process definition keys is empty
Error message
Set of process definition keys is empty
What it means
ProcessInstanceQuery.processDefinitionKeys() rejects an empty set of process definition keys. The library requires at least one key because an empty 'IN' clause would produce invalid or meaningless SQL when filtering process instances. Throwing early gives a clear ActivitiIllegalArgumentException instead of a confusing query failure later.
Solutions
- Guard the caller: only call processDefinitionKeys when the set is non-empty; otherwise skip adding that filter entirely.
- If an empty set means 'no filter', omit the call rather than passing the empty set.
- If an empty set should mean 'match nothing', use processDefinitionKeys with a sentinel key or handle the no-result case before querying.
- Catch ActivitiIllegalArgumentException around query construction to surface a friendly validation message to the user.
Example fix
// before
query.processDefinitionKeys(keys); // keys may be empty
// after
if (keys != null && !keys.isEmpty()) {
query.processDefinitionKeys(keys);
} Defensive patterns
Strategy: validation
Validate before calling
if (keys == null || keys.isEmpty()) {
throw new IllegalArgumentException("processDefinitionKeys must contain at least one key");
}
query.processDefinitionKeys(keys); Type guard
boolean isValidKeySet(Set<String> keys) {
return keys != null && !keys.isEmpty();
} Try / catch
try {
query.processDefinitionKeys(keys);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
// handle empty/null key set, e.g. skip filter or return 400
} Prevention
- Treat an empty set as 'no filter' and skip the call.
- Validate collections before passing them into query builders.
- Add unit tests for empty-collection inputs to query construction code.
When it happens
Trigger: Calling processInstanceQuery().processDefinitionKeys(keys) with a non-null but empty Set<String>, e.g. new HashSet<>() or a set filtered down to zero entries before the query is built.
Common situations: Building queries dynamically from user-selected filters where no process definitions were selected; collecting keys from configuration or a database lookup that returned nothing; generics-era refactors where code previously passed null (handled separately) and now passes an empty collection.
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
- Involved user is null
- name is null
- process definition tenantId is null
- Set of process instance ids is empty
- value is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/62026fef41dfd720.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/ProcessInstanceQueryImpl.java:282
if (processDefinitionKey == null) {
throw new ActivitiIllegalArgumentException("Process definition key is null");
}
if (inOrStatement) {
this.currentOrQueryObject.processDefinitionKey = processDefinitionKey;
} else {
this.processDefinitionKey = processDefinitionKey;
}
return this;
}
@Override
public ProcessInstanceQuery processDefinitionKeys(Set<String> processDefinitionKeys) {
if (processDefinitionKeys == null) {
throw new ActivitiIllegalArgumentException("Set of process definition keys is null");
}
if (processDefinitionKeys.isEmpty()) {
throw new ActivitiIllegalArgumentException("Set of process definition keys is empty");
}
if (inOrStatement) {
this.currentOrQueryObject.processDefinitionKeys = processDefinitionKeys;
} else {
this.processDefinitionKeys = processDefinitionKeys;
}
return this;
}
@Override
public ProcessInstanceQueryImpl deploymentId(String deploymentId) {
if (inOrStatement) {
this.currentOrQueryObject.deploymentId = deploymentId;
} else {
this.deploymentId = deploymentId;
}
return this;View on GitHub (pinned to d6d39ce1c6)