flowable/flowable-engine · error · FlowableIllegalArgumentException

createdAfter is null

Error message

createdAfter is null

What it means

Thrown by PlanItemInstanceQueryImpl.planItemInstanceCreatedAfter when the createdAfter Date is null. The engine requires a concrete date for the lower bound of the created-time filter and rejects null at builder time.

Solutions

  1. Pass a valid java.util.Date for the lower bound.
  2. Null-check and skip the filter when the caller did not specify a start date.
  3. Use planItemInstanceCreatedBefore for the upper bound and combine both for a bounded range.

Example fix

// before
query.planItemInstanceCreatedAfter(range.getStart()); // may be null
// after
if (range.getStart() != null) {
    query.planItemInstanceCreatedAfter(range.getStart());
}
Defensive patterns

Strategy: validation

Validate before calling

if (createdAfter != null) {
    planItemInstanceQuery.planItemInstanceCreatedAfter(createdAfter);
} // else: unbounded start

Type guard

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

Try / catch

try {
    query.planItemInstanceCreatedAfter(createdAfter);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("createdAfter is null")) {
        // omit the lower bound and continue
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling planItemInstanceCreatedAfter(null), commonly when the range start comes from a nullable request parameter or a failed date parse.

Common situations: 'since' filter omitted in an API call; a JSON date field missing in the payload mapped to null; calendar/date arithmetic producing null on error paths.

Related errors


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

Appendix: source

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

    }

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

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

    @Override
    public PlanItemInstanceQuery planItemInstanceLastAvailableBefore(Date availableBefore) {
        if (availableBefore == null) {
            throw new FlowableIllegalArgumentException("availableBefore is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.lastAvailableBefore = availableBefore;
        } else {
            this.lastAvailableBefore = availableBefore;

View on GitHub (pinned to d6d39ce1c6)