flowable/flowable-engine · error · FlowableIllegalArgumentException

endedAfter is null

Error message

endedAfter is null

What it means

Flowable's PlanItemInstanceQueryImpl.planItemInstanceEndedAfter(Date) validates its argument and throws FlowableIllegalArgumentException when a null Date is passed. Query criteria setters in Flowable refuse null because null is not a filterable value; omit the criteria entirely instead of passing null. This fail-fast behavior prevents silently unfiltered or broken SQL queries.

Solutions

  1. Check the Date for null before calling planItemInstanceEndedAfter and skip the criteria when null
  2. If a null filter means 'all', simply do not add the endedAfter criterion to the query
  3. Verify the date source (parser, DTO field, calculation) actually produced a non-null value
  4. Catch FlowableIllegalArgumentException around query construction if inputs are untrusted

Example fix

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

Strategy: validation

Validate before calling

if (endedAfter != null) {
    query.planItemInstanceEndedAfter(endedAfter);
}

Type guard

boolean hasEndedAfter = (endedAfter instanceof Date);

Try / catch

try {
    query.planItemInstanceEndedAfter(endedAfter);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Ignoring endedAfter filter: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling planItemInstanceQuery.planItemInstanceEndedAfter(null) directly, or passing a Date variable that was never initialized (e.g. a method parameter or computed date that resolved to null).

Common situations: Developers building dynamic query builders that conditionally populate a Date but pass it unconditionally; parsing user-supplied dates with a parser returning null on failure; nullable fields mapped from REST request bodies.

Related errors


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

Appendix: source

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

    }

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

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

    @Override
    public PlanItemInstanceQuery ended() {
        if (inOrStatement) {
            this.currentOrQueryObject.ended = true;
            includeEnded = true;
        } else {
            this.ended = true;
        }
        return this;

View on GitHub (pinned to d6d39ce1c6)