flowable/flowable-engine · error · FlowableIllegalArgumentException

planItemDefinitionIds is null

Error message

planItemDefinitionIds is null

What it means

Flowable's CaseInstanceQueryImpl throws FlowableIllegalArgumentException when activePlanItemDefinitionIds(Set<String>) is called with a null set. The query builder validates arguments eagerly so that an invalid query fails at construction time rather than producing a broken SQL query at execution time.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java:799

    }
    
    @Override
    public CaseInstanceQuery activePlanItemDefinitionId(String planItemDefinitionId) {
        if (planItemDefinitionId == null) {
            throw new FlowableIllegalArgumentException("planItemDefinitionId is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.activePlanItemDefinitionId = planItemDefinitionId;
        } else {
            this.activePlanItemDefinitionId = planItemDefinitionId;
        }
        return this;
    }
    
    @Override
    public CaseInstanceQuery activePlanItemDefinitionIds(Set<String> planItemDefinitionIds) {
        if (planItemDefinitionIds == null) {
            throw new FlowableIllegalArgumentException("planItemDefinitionIds is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.activePlanItemDefinitionIds = planItemDefinitionIds;
        } else {
            this.activePlanItemDefinitionIds = planItemDefinitionIds;
        }
        return this;
    }
    
    @Override
    public CaseInstanceQuery involvedUser(String userId) {
        if (userId == null) {
            throw new FlowableIllegalArgumentException("involvedUser is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.involvedUser = userId;
        } else {
            this.involvedUser = userId;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the caller computes a non-null Set before calling activePlanItemDefinitionIds (e.g. Collections.emptySet() when no filter is intended).
  2. If the filter is optional, only call activePlanItemDefinitionIds when the set is non-null instead of always calling it.
  3. Trace where the null set originates (config, DB lookup, REST payload) and fix that producer to return an empty set.
  4. Wrap the call and surface a clear message to the end user that the planItemDefinitionIds filter was missing.

Example fix

// before
query.activePlanItemDefinitionIds(filter.getPlanItemDefinitionIds());
// after
if (filter.getPlanItemDefinitionIds() != null) {
    query.activePlanItemDefinitionIds(filter.getPlanItemDefinitionIds());
}
Defensive patterns

Strategy: validation

Validate before calling

if (planItemDefinitionIds == null) {
    throw new IllegalArgumentException("planItemDefinitionIds must not be null");
}
query.activePlanItemDefinitionIds(planItemDefinitionIds);

Type guard

boolean isValidFilter(Set<String> ids) {
    return ids != null;
}

Try / catch

try {
    query.activePlanItemDefinitionIds(ids);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Invalid planItemDefinitionIds filter: {}", e.getMessage());
    // rethrow or fall back to unfiltered query
}

Prevention

When it happens

Trigger: Calling caseInstanceQuery().activePlanItemDefinitionIds(null) directly, or passing a null field/variable into the method, either at top level or inside an or() block.

Common situations: Building queries dynamically where the set of plan item definition ids comes from an upstream lookup or configuration that returned null (e.g. a missing deployment, a null return from a service, or an uninitialized field in a search filter DTO).

Related errors


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