flowable/flowable-engine · error · FlowableIllegalArgumentException

suspendedAfter is null

Error message

suspendedAfter is null

What it means

planItemInstanceLastSuspendedAfter(Date) throws FlowableIllegalArgumentException 'suspendedAfter is null' when given a null Date. The validation sits in the builder method of PlanItemInstanceQueryImpl, so the rejection happens immediately, covering both the plain and OR-statement query objects. Null is not an accepted filter value.

Solutions

  1. Provide a non-null Date argument.
  2. Only chain the filter when the date is present.
  3. Normalize absent values to a default date before querying.
  4. Handle FlowableIllegalArgumentException as fallback and drop the filter.

Example fix

// before
query.planItemInstanceLastSuspendedAfter(filter.suspendedAfter); // null
// after
if (filter.suspendedAfter != null) {
    query.planItemInstanceLastSuspendedAfter(filter.suspendedAfter);
}
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try {
    query.planItemInstanceLastSuspendedAfter(suspendedAfter);
} catch (FlowableIllegalArgumentException e) {
    query = cmmnRuntimeService.createPlanItemInstanceQuery();
}

Prevention

When it happens

Trigger: Invoking planItemInstanceLastSuspendedAfter(null), e.g. from an unpopulated filter object or a null returned by a date utility.

Common situations: Optional suspended-after filters in monitoring dashboards; null from failed parsing of client timestamps; batch report code composing filters from sparse data; tests of builder validation.

Related errors


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

Appendix: source

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

    }

    @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;
        }
        return this;
    }

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

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

View on GitHub (pinned to d6d39ce1c6)