flowable/flowable-engine · error · FlowableIllegalArgumentException

Set of process definition ids is empty

Error message

Set of process definition ids is empty

What it means

ProcessInstanceQueryImpl.processDefinitionIds(Set<String>) throws FlowableIllegalArgumentException('Set of process definition ids is empty') when the supplied set is non-null but has no elements. An empty set would produce an invalid or always-false IN() clause, so Flowable rejects it explicitly right after the null check, before storing the value on the query or OR-query object.

Solutions

  1. Check isEmpty() before calling and skip the filter (or return an empty result immediately) when the set is empty
  2. Decide explicitly: an empty set should usually mean 'return nothing' — short-circuit with query.listPage(0,0) or an impossible filter instead
  3. Investigate why the id set is empty (permission/tenant logic) if that state is unexpected
  4. Catch FlowableIllegalArgumentException around query construction to give a precise message

Example fix

// before
Set<String> ids = resolvePermittedDefinitionIds(user);
query.processDefinitionIds(ids); // throws when user has no permissions

// after
Set<String> ids = resolvePermittedDefinitionIds(user);
if (ids == null || ids.isEmpty()) {
    return Collections.emptyList(); // no permitted definitions -> no results
}
query.processDefinitionIds(ids);
Defensive patterns

Strategy: validation

Validate before calling

if (ids == null || ids.isEmpty()) {
    return Collections.emptyList(); // nothing can match an empty IN clause
}
query.processDefinitionIds(ids);

Type guard

boolean hasIds(Set<String> ids) { return ids != null && !ids.isEmpty(); }

Try / catch

try {
    query.processDefinitionIds(ids);
} catch (FlowableIllegalArgumentException e) {
    return Collections.emptyList(); // empty set = no matches by convention
}

Prevention

When it happens

Trigger: Calling .processDefinitionIds(Collections.emptySet()) or passing a set that was filtered down to zero elements (e.g. no definitions match the user's permissions, or ids were removed before the call).

Common situations: Multi-tenant apps where a user belongs to no tenant and the permitted-definition set ends up empty; batch jobs whose filter criteria matched nothing; tests passing an empty set expecting 'no filter' semantics.

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/7f1dc73f25cb636c. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/ProcessInstanceQueryImpl.java:423

        if (processDefinitionId == null) {
            throw new FlowableIllegalArgumentException("Process definition id is null");
        }

        if (inOrStatement) {
            this.currentOrQueryObject.processDefinitionId = processDefinitionId;
        } else {
            this.processDefinitionId = processDefinitionId;
        }
        return this;
    }

    @Override
    public ProcessInstanceQuery processDefinitionIds(Set<String> processDefinitionIds) {
        if (processDefinitionIds == null) {
            throw new FlowableIllegalArgumentException("Set of process definition ids is null");
        }
        if (processDefinitionIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("Set of process definition ids is empty");
        }

        if (inOrStatement) {
            this.currentOrQueryObject.processDefinitionIds = processDefinitionIds;
        } else {
            this.processDefinitionIds = processDefinitionIds;
        }
        return this;
    }

    @Override
    public ProcessInstanceQueryImpl processDefinitionKey(String processDefinitionKey) {
        if (processDefinitionKey == null) {
            throw new FlowableIllegalArgumentException("Process definition key is null");
        }

        if (inOrStatement) {
            this.currentOrQueryObject.processDefinitionKey = processDefinitionKey;

View on GitHub (pinned to d6d39ce1c6)