flowable/flowable-engine · error · FlowableIllegalArgumentException

startedAfter is null

Error message

startedAfter is null

What it means

planItemInstanceLastStartedAfter(Date) throws FlowableIllegalArgumentException 'startedAfter is null' when the argument is null. Like all date filters in PlanItemInstanceQueryImpl, null is rejected eagerly in the builder because it cannot produce a valid SQL bound. The filter must be a concrete Date or simply not applied.

Solutions

  1. Supply a valid Date instance.
  2. Apply the filter conditionally only when the value is non-null.
  3. Default the value at the API boundary before query construction.
  4. Catch FlowableIllegalArgumentException and fall back to a query without the filter.

Example fix

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

Strategy: validation

Validate before calling

if (startedAfter == null) {
    throw new IllegalArgumentException("startedAfter must be a non-null Date");
}
query.planItemInstanceLastStartedAfter(startedAfter);

Type guard

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

Try / catch

try {
    query.planItemInstanceLastStartedAfter(startedAfter);
} catch (FlowableIllegalArgumentException e) {
    query = cmmnRuntimeService.createPlanItemInstanceQuery();
}

Prevention

When it happens

Trigger: Calling planItemInstanceLastStartedAfter(null), e.g. when a report period's start bound was never computed or a request field was omitted.

Common situations: Time-range report builders with optional bounds; null from date-range parsing of user input; microservice payloads missing the field; tests invoking builders with null to verify validation.

Related errors


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

Appendix: source

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

    }

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

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

    @Override
    public PlanItemInstanceQuery planItemInstanceLastSuspendedBefore(Date suspendedBefore) {
        if (suspendedBefore == null) {
            throw new FlowableIllegalArgumentException("suspendedBefore is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.lastSuspendedBefore = suspendedBefore;
        } else {
            this.lastSuspendedBefore = suspendedBefore;

View on GitHub (pinned to d6d39ce1c6)