flowable/flowable-engine · error · FlowableIllegalArgumentException

unavailableAfter is null

Error message

unavailableAfter is null

What it means

planItemInstanceLastUnavailableAfter(Date) on PlanItemInstanceQueryImpl requires a non-null Date and throws FlowableIllegalArgumentException when unavailableAfter is null. The Flowable CMMN query API validates every filter argument eagerly in the builder so that invalid queries fail at construction time instead of producing broken SQL at execution time. Passing null means no meaningful date filter was supplied, so the library refuses the call.

Source

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

    }

    @Override
    public PlanItemInstanceQuery planItemInstanceLastUnavailableBefore(Date unavailableBefore) {
        if (unavailableBefore == null) {
            throw new FlowableIllegalArgumentException("unavailableBefore is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.lastUnavailableBefore = unavailableBefore;
        } else {
            this.lastUnavailableBefore = unavailableBefore;
        }
        return this;
    }

    @Override
    public PlanItemInstanceQuery planItemInstanceLastUnavailableAfter(Date unavailableAfter) {
        if (unavailableAfter == null) {
            throw new FlowableIllegalArgumentException("unavailableAfter is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.lastUnavailableAfter = unavailableAfter;
        } else {
            this.lastUnavailableAfter = unavailableAfter;
        }
        return this;
    }

    @Override
    public PlanItemInstanceQuery planItemInstanceLastEnabledBefore(Date enabledBefore) {
        if (enabledBefore == null) {
            throw new FlowableIllegalArgumentException("enabledBefore is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.lastEnabledBefore = enabledBefore;
        } else {
            this.lastEnabledBefore = enabledBefore;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure a non-null Date is passed, e.g. planItemInstanceLastUnavailableAfter(new Date()) or a parsed value.
  2. Skip calling planItemInstanceLastUnavailableAfter entirely when the filter is not provided (conditional builder chaining).
  3. Default the value at the caller boundary, e.g. Optional.ofNullable(request.getUnavailableAfter()).orElse(defaultDate).
  4. Catch FlowableIllegalArgumentException if null is an acceptable input and fall back to an unfiltered query.

Example fix

// before
query.planItemInstanceLastUnavailableAfter(request.getUnavailableAfter()); // NPE-ish throw when null
// after
if (request.getUnavailableAfter() != null) {
    query.planItemInstanceLastUnavailableAfter(request.getUnavailableAfter());
}
Defensive patterns

Strategy: validation

Validate before calling

if (unavailableAfter == null) {
    throw new IllegalArgumentException("unavailableAfter filter requires a non-null Date; omit the filter instead");
}
query.planItemInstanceLastUnavailableAfter(unavailableAfter);

Type guard

boolean hasFilter(Date d) { return d != null; }

Try / catch

try {
    query.planItemInstanceLastUnavailableAfter(date);
} catch (FlowableIllegalArgumentException e) {
    // rebuild query without the unavailableAfter filter
    query = cmmnRuntimeService.createPlanItemInstanceQuery();
}

Prevention

When it happens

Trigger: Calling createPlanItemInstanceQuery().planItemInstanceLastUnavailableAfter(null), typically when the date is the result of an uninitialized/unassigned variable or an unpopulated request parameter that was passed straight into the query builder.

Common situations: REST/search endpoints where the client omits an 'unavailableAfter' filter and the handler passes the null parsed value into the builder; bean/form binding leaving the Date field null; refactors that changed a default date to null; OR-statement code paths reusing an unset variable.

Related errors


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