flowable/flowable-engine · error · ActivitiIllegalArgumentException

Set of process instance ids is empty

Error message

Set of process instance ids is empty

What it means

processInstanceIds(Set) additionally throws ActivitiIllegalArgumentException('Set of process instance ids is empty') when the provided set has no elements, because an IN () clause is invalid and would silently match nothing.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/ProcessInstanceQueryImpl.java:115

    public ProcessInstanceQueryImpl processInstanceId(String processInstanceId) {
        if (processInstanceId == null) {
            throw new ActivitiIllegalArgumentException("Process instance id is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.executionId = processInstanceId;
        } else {
            this.executionId = processInstanceId;
        }
        return this;
    }

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

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

    @Override
    public ProcessInstanceQuery processInstanceBusinessKey(String businessKey) {
        if (businessKey == null) {
            throw new ActivitiIllegalArgumentException("Business key is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.businessKey = businessKey;
        } else {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Short-circuit: if the set is empty, return an empty result without executing the query
  2. Ensure upstream collection logic always leaves at least one id, or handle the empty case explicitly
  3. Use processInstanceId() for the single-id case after confirming size()==1 if appropriate
  4. Catch ActivitiIllegalArgumentException and treat it as 'no matches'

Example fix

// before
runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
// after
if (ids == null || ids.isEmpty()) {
    return Collections.emptyList();
}
runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list();
Defensive patterns

Strategy: validation

Validate before calling

if (ids == null || ids.isEmpty()) {
    return Collections.emptyList(); // skip query entirely
}
query.processInstanceIds(ids);

Type guard

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

Try / catch

try {
    query.processInstanceIds(ids);
} catch (ActivitiIllegalArgumentException e) {
    return Collections.emptyList(); // treat empty as no matches
}

Prevention

When it happens

Trigger: Calling ProcessInstanceQuery.processInstanceIds(new HashSet<>()) or passing a set that was emptied by upstream filtering (e.g. intersection of permissions produced zero ids).

Common situations: Filter UIs where the user deselects all ids; permission-intersection code that legitimately yields an empty set but still issues the query.

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