flowable/flowable-engine · error · ActivitiIllegalArgumentException

Process instance id list is empty

Error message

Process instance id list is empty

What it means

HistoricTaskInstanceQueryImpl.processInstanceIdIn() throws ActivitiIllegalArgumentException when the supplied process instance id list is non-null but empty. The library requires at least one id because an SQL IN clause with no values would be invalid or return nothing. Pass a non-empty list of process instance ids.

Solutions

  1. Ensure the list passed to processInstanceIdIn contains at least one process instance id before building the query.
  2. If the id list may be empty, skip the query or use a different filter entirely instead of calling processInstanceIdIn.
  3. Guard the call with a size check: if (ids != null && !ids.isEmpty()) query.processInstanceIdIn(ids);

Example fix

// before
List<String> ids = collectIds(); // may be empty
query.processInstanceIdIn(ids);

// after
List<String> ids = collectIds();
if (!ids.isEmpty()) {
    query.processInstanceIdIn(ids);
} else {
    return Collections.emptyList(); // no candidates, skip query
}
Defensive patterns

Strategy: validation

Validate before calling

if (processInstanceIds == null || processInstanceIds.isEmpty()) { throw new IllegalArgumentException("processInstanceIds must contain at least one id"); }
for (String id : processInstanceIds) { if (id == null) { throw new IllegalArgumentException("processInstanceIds must not contain nulls"); } }

Type guard

static boolean isUsableIdList(List<String> ids) { return ids != null && !ids.isEmpty() && ids.stream().allMatch(Objects::nonNull); }

Try / catch

try {
    query.processInstanceIdIn(ids);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
    log.warn("Invalid processInstanceIdIn argument: {}", e.getMessage());
    // fall back to unfiltered query or return empty result
}

Prevention

When it happens

Trigger: Calling historicTaskInstanceQuery.processInstanceIdIn(new ArrayList<>()) (or any empty List<String>) on the query object.

Common situations: Building the id list dynamically from an upstream search that matched nothing; passing a collection that was filtered to empty; wiring a default empty collection into query construction.

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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/HistoricTaskInstanceQueryImpl.java:165

    }

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

    @Override
    public HistoricTaskInstanceQueryImpl processInstanceIdIn(List<String> processInstanceIds) {
        if (processInstanceIds == null) {
            throw new ActivitiIllegalArgumentException("Process instance id list is null");
        }
        if (processInstanceIds.isEmpty()) {
            throw new ActivitiIllegalArgumentException("Process instance id list is empty");
        }
        for (String processInstanceId : processInstanceIds) {
            if (processInstanceId == null) {
                throw new ActivitiIllegalArgumentException("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 processInstanceBusinessKey(String processInstanceBusinessKey) {
        if (inOrStatement) {

View on GitHub (pinned to d6d39ce1c6)