flowable/flowable-engine · error · FlowableIllegalArgumentException

planItemDefinitionId is null

Error message

planItemDefinitionId is null

What it means

HistoricCaseInstanceQueryImpl.activePlanItemDefinitionId(String) throws FlowableIllegalArgumentException when the plan item definition id is null. A null id cannot be used in the generated SQL predicate for filtering historic case instances by active plan item, so the library fails fast.

Source

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

    public HistoricCaseInstanceQuery includeCaseVariables() {
        this.includeCaseVariables = true;
        return this;
    }

    @Override
    public HistoricCaseInstanceQuery includeCaseVariables(Collection<String> variableNames) {
        if (variableNames == null || variableNames.isEmpty()) {
            throw new FlowableIllegalArgumentException("variableNames is null or empty");
        }
        includeCaseVariables();
        this.variableNamesToInclude = new LinkedHashSet<>(variableNames);
        return this;
    }

    @Override
    public HistoricCaseInstanceQuery 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 HistoricCaseInstanceQuery activePlanItemDefinitionIds(Set<String> planItemDefinitionIds) {
        if (planItemDefinitionIds == null) {
            throw new FlowableIllegalArgumentException("planItemDefinitionIds is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.activePlanItemDefinitionIds = planItemDefinitionIds;
        } else {
            this.activePlanItemDefinitionIds = planItemDefinitionIds;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the plan item definition id is non-null before calling, e.g. Objects.requireNonNull(planItemDefinitionId, ...) at the call site.
  2. Check the case model/repository actually contains the plan item definition and you copied the correct id.
  3. If the value is optional, only add the filter when the id is present.
  4. If multiple ids may apply, use activePlanItemDefinitionIds(Set) with a non-null set instead.

Example fix

// before
query.activePlanItemDefinitionId(planItemDefinitionId); // may be null
// after
if (planItemDefinitionId != null) {
    query.activePlanItemDefinitionId(planItemDefinitionId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (planItemDefinitionId == null || planItemDefinitionId.isEmpty()) {
    throw new IllegalArgumentException("planItemDefinitionId is required");
}
query.activePlanItemDefinitionId(planItemDefinitionId);

Type guard

boolean hasText(String s) {
    return s != null && !s.trim().isEmpty();
}

Try / catch

try {
    query.activePlanItemDefinitionId(planItemDefinitionId);
} catch (FlowableIllegalArgumentException e) {
    if ("planItemDefinitionId is null".equals(e.getMessage())) {
        // skip filter or rethrow with context
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling activePlanItemDefinitionId(null) on a HistoricCaseInstanceQuery, directly or inside an or() block (currentOrQueryObject), before executing the query.

Common situations: The plan item definition id is looked up from a model/config value that is missing; passing a variable that was never initialized; refactoring code where the id source was removed.

Related errors


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