flowable/flowable-engine · error · FlowableIllegalArgumentException

Set of case instance ids is null

Error message

Set of case instance ids is null

What it means

HistoricPlanItemInstanceQueryImpl.planItemInstanceCaseInstanceIds() requires a non-null Set of case instance ids; a null set raises FlowableIllegalArgumentException. The query API distinguishes null (programming error) from not calling the method (no filter).

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricPlanItemInstanceQueryImpl.java:182

            this.derivedCaseDefinitionId = derivedCaseDefinitionId;
        }
        return this;
    }

    @Override
    public HistoricPlanItemInstanceQuery planItemInstanceCaseInstanceId(String caseInstanceId) {
        if (inOrStatement) {
            this.currentOrQueryObject.caseInstanceId = caseInstanceId;
        } else {
            this.caseInstanceId = caseInstanceId;
        }
        return this;
    }

    @Override
    public HistoricPlanItemInstanceQuery planItemInstanceCaseInstanceIds(Set<String> caseInstanceIds) {
        if (caseInstanceIds == null) {
            throw new FlowableIllegalArgumentException("Set of case instance ids is null");
        }
        if (caseInstanceIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("Set of case instance ids is empty");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.caseInstanceIds = caseInstanceIds;
        } else {
            this.caseInstanceIds = caseInstanceIds;
        }
        return this;
    }

    @Override
    public HistoricPlanItemInstanceQuery planItemInstanceStageInstanceId(String stageInstanceId) {
        if (inOrStatement) {
            this.currentOrQueryObject.stageInstanceId = stageInstanceId;
        } else {
            this.stageInstanceId = stageInstanceId;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Null-check the set before calling and skip the filter when null
  2. Initialize the collection to an empty Set and only call the method when non-empty
  3. Ensure the upstream code path that should populate the set actually runs
  4. Use planItemInstanceCaseInstanceId for a single id instead of a set

Example fix

// before
query.planItemInstanceCaseInstanceIds(ids).list();
// after
if (ids != null && !ids.isEmpty()) {
    query.planItemInstanceCaseInstanceIds(ids);
}
List<HistoricPlanItemInstance> results = query.list();
Defensive patterns

Strategy: validation

Validate before calling

if (ids != null && !ids.isEmpty()) {
    query.planItemInstanceCaseInstanceIds(ids);
}

Type guard

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

Try / catch

try {
    query.planItemInstanceCaseInstanceIds(ids);
} catch (FlowableIllegalArgumentException e) {
    if (!e.getMessage().contains("Set of case instance ids is null")) throw e;
    // fall back to unfiltered query or return empty result
}

Prevention

When it happens

Trigger: Calling planItemInstanceCaseInstanceIds(null), often from a map lookup or variable initialized to null instead of an empty/collection value.

Common situations: Passing the result of a cache/config lookup that returned null; framework deserializers producing null for absent list parameters.

Related errors


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