flowable/flowable-engine · error · ActivitiIllegalArgumentException

Process instance id list is null

Error message

Process instance id list is null

What it means

HistoricTaskInstanceQueryImpl.processInstanceIdIn(List<String>) validates the list of process instance ids before building the query: it must be non-null and non-empty, and (as the surrounding code shows) no element may be null. The null-list case throws ActivitiIllegalArgumentException with 'Process instance id list is null'.

Solutions

  1. Initialize the list before calling, e.g. new ArrayList<>(ids).
  2. Guard the call: only apply the filter when the list is non-null and non-empty; otherwise skip it or short-circuit the search.
  3. Null-check every element too, since individual null ids are also rejected.
  4. Fix the producer that returns null lists so it returns empty collections instead.

Example fix

// before
List<String> ids = (List<String>) cache.get("pids"); // null
query.processInstanceIdIn(ids);
// after
List<String> ids = (List<String>) cache.get("pids");
if (ids != null && !ids.isEmpty()) {
    query.processInstanceIdIn(ids);
} else {
    return Collections.emptyList();
}
Defensive patterns

Strategy: validation

Validate before calling

if (processInstanceIds == null || processInstanceIds.isEmpty()) {
    return Collections.emptyList(); // or skip the filter
}
if (processInstanceIds.contains(null)) {
    throw new IllegalArgumentException("null element in processInstanceIds");
}

Type guard

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

Try / catch

try {
    query.processInstanceIdIn(ids);
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().contains("id list is null")) {
        // treat as missing input: skip filter or fail with a domain error
    }
}

Prevention

When it happens

Trigger: Calling processInstanceIdIn(null) — usually a list that failed to load, an unguarded Optional.map chain, or a mapped request body missing the field.

Common situations: Job orchestrators forwarding id lists produced by an earlier step that returned nothing; REST payloads with an absent/incorrectly-named field deserialized to null; cache lookups that return null instead of an empty list.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/1b1f2f74801ffdc9. Report an issue: GitHub.

Appendix: source

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

                    .getHistoricTaskInstanceEntityManager()
                    .findHistoricTaskInstancesByQueryCriteria(this);
        }
    }

    @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;
    }

View on GitHub (pinned to d6d39ce1c6)