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

  1. Only call planItemDefinitionTypes when the list is non-empty; otherwise omit the filter to match all types.
  2. If the empty list should mean 'match nothing', add an impossible criterion deliberately or short-circuit the query and return no results.
  3. 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

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


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)