flowable/flowable-engine · error · FlowableIllegalArgumentException
Plan item definition types is empty
Error message
Plan item definition types is empty
What it means
Thrown by PlanItemInstanceQueryImpl.planItemDefinitionTypes when the list is empty. An empty IN-clause is invalid/meaningless SQL, so the builder rejects it immediately. Unlike the null check, this indicates data was present structurally but contained no values.
Solutions
- Only call planItemDefinitionTypes when the list is non-empty; otherwise omit the filter to match all types.
- If the empty list should mean 'match nothing', add an impossible criterion deliberately or short-circuit the query and return no results.
- Populate the list with valid types such as "task", "humanTask", "stage".
Example fix
// before
query.planItemDefinitionTypes(selectedTypes); // selectedTypes may be empty
// after
if (selectedTypes != null && !selectedTypes.isEmpty()) {
query.planItemDefinitionTypes(selectedTypes);
} Defensive patterns
Strategy: validation
Validate before calling
if (types != null && !types.isEmpty()) {
planItemInstanceQuery.planItemDefinitionTypes(types);
} // else: omit the filter to match all types Type guard
boolean isNonEmpty(List<String> list) {
return list != null && !list.isEmpty();
} Try / catch
try {
query.planItemDefinitionTypes(types);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().contains("Plan item definition types is empty")) {
// rebuild the query without the types filter
} else {
throw e;
}
} Prevention
- Treat an empty multi-select as 'no filter', not as an empty IN clause
- Check list emptiness before handing collections to query builders
- Document that empty collections are rejected by Flowable query APIs
When it happens
Trigger: Calling planItemInstanceQuery.planItemDefinitionTypes(Collections.emptyList()) or passing a newly-created List<String>() with no elements, often from an empty UI multi-select or empty query parameter.
Common situations: Users submit a filter form with no types checked; a JSON body like {"types": []} is mapped straight into the query builder.
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
- groupIds are empty
- ids is an empty collection
- Set of case instance ids is empty
- activatedBefore is null
- assignee is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/a7095d43a6f0740b.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java:248
public PlanItemInstanceQuery planItemDefinitionType(String planItemDefinitionType) {
if (planItemDefinitionType == null) {
throw new FlowableIllegalArgumentException("Plan item definition type is null");
}
if (inOrStatement) {
this.currentOrQueryObject.planItemDefinitionType = planItemDefinitionType;
} else {
this.planItemDefinitionType = planItemDefinitionType;
}
return this;
}
@Override
public PlanItemInstanceQuery planItemDefinitionTypes(List<String> planItemDefinitionTypes) {
if (planItemDefinitionTypes == null) {
throw new FlowableIllegalArgumentException("Plan item definition types is null");
}
if (planItemDefinitionTypes.isEmpty()) {
throw new FlowableIllegalArgumentException("Plan item definition types is empty");
}
if (inOrStatement) {
this.currentOrQueryObject.planItemDefinitionTypes = planItemDefinitionTypes;
} else {
this.planItemDefinitionTypes = planItemDefinitionTypes;
}
return this;
}
@Override
public PlanItemInstanceQuery planItemInstanceName(String name) {
if (name == null) {
throw new FlowableIllegalArgumentException("Name is null");
}
if (inOrStatement) {
this.currentOrQueryObject.name = name;
} else {
this.name = name;View on GitHub (pinned to d6d39ce1c6)