flowable/flowable-engine · error · FlowableIllegalArgumentException

Process instance id list is empty

Error message

Process instance id list is empty

What it means

HistoricTaskInstanceQueryImpl.processInstanceIdIn(Collection<String>) rejects an empty collection with FlowableIllegalArgumentException('Process instance id list is empty') because an IN predicate over zero values would produce invalid/meaningless SQL. The caller must supply at least one process instance id.

Solutions

  1. Skip adding the predicate when the list is empty and return no results directly (an IN () can never match).
  2. Only call processInstanceIdIn when !ids.isEmpty(); otherwise short-circuit to an empty result page.
  3. Fix upstream filtering that unintentionally removes all ids.

Example fix

// before
query.processInstanceIdIn(candidateIds); // candidateIds may be empty -> exception

// after
if (candidateIds.isEmpty()) {
    return Collections.emptyList(); // no instances -> no tasks can match
}
query.processInstanceIdIn(candidateIds);
Defensive patterns

Strategy: validation

Validate before calling

if (processInstanceIds == null || processInstanceIds.isEmpty()) {
    return Collections.emptyList(); // IN () can never match
}

Type guard

boolean isUsableIdList(Collection<String> c) { return c != null && !c.isEmpty(); }

Prevention

When it happens

Trigger: Calling processInstanceIdIn(Collections.emptyList()) or a list that was filtered down to zero elements right before the query executes.

Common situations: Collecting candidate process instance ids upstream (e.g. from a search that matched nothing) and passing the empty result straight into the query; over-aggressive filtering removing all ids.

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

Appendix: source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:304

    }

    @Override
    public HistoricTaskInstanceQueryImpl processInstanceId(String processInstanceId) {
        if (inOrStatement) {
            this.currentOrQueryObject.processInstanceId = processInstanceId;
        } else {
            this.processInstanceId = processInstanceId;
        }
        return this;
    }

    @Override
    public HistoricTaskInstanceQueryImpl processInstanceIdIn(Collection<String> processInstanceIds) {
        if (processInstanceIds == null) {
            throw new FlowableIllegalArgumentException("Process instance id list is null");
        }
        if (processInstanceIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("Process instance id list is empty");
        }
        for (String processInstanceId : processInstanceIds) {
            if (processInstanceId == null) {
                throw new FlowableIllegalArgumentException("None of the given process instance ids can be null");
            }
        }

        if (inOrStatement) {
            this.currentOrQueryObject.processInstanceIds = processInstanceIds;
        } else {
            this.processInstanceIds = processInstanceIds;
        }
        return this;
    }
    
    @Override
    public HistoricTaskInstanceQueryImpl withoutProcessInstanceId() {
        if (inOrStatement) {

View on GitHub (pinned to d6d39ce1c6)