flowable/flowable-engine · error · FlowableIllegalArgumentException
suspendedBefore is null
Error message
suspendedBefore is null
What it means
planItemInstanceLastSuspendedBefore(Date) requires a non-null suspendedBefore Date and throws FlowableIllegalArgumentException 'suspendedBefore is null' otherwise. The CMMN query builder validates each filter argument so invalid queries fail at construction time. Null cannot be turned into a comparison predicate.
Solutions
- Pass a concrete Date (e.g. new Date() or a stored suspension timestamp).
- Guard the call with a null check and omit the filter when absent.
- Substitute a default boundary date when the value is unknown.
- Catch FlowableIllegalArgumentException and rebuild without the suspension filter.
Example fix
// before
query.planItemInstanceLastSuspendedBefore(item.getLastSuspendedTime()); // null if never suspended
// after
if (item.getLastSuspendedTime() != null) {
query.planItemInstanceLastSuspendedBefore(item.getLastSuspendedTime());
} Defensive patterns
Strategy: validation
Validate before calling
if (suspendedBefore == null) {
throw new IllegalArgumentException("suspendedBefore must be a non-null Date");
}
query.planItemInstanceLastSuspendedBefore(suspendedBefore); Type guard
boolean hasDate(Date d) { return d != null; } Try / catch
try {
query.planItemInstanceLastSuspendedBefore(suspendedBefore);
} catch (FlowableIllegalArgumentException e) {
query = cmmnRuntimeService.createPlanItemInstanceQuery();
} Prevention
- Handle entities that were never suspended (null timestamps) before querying
- Null-guard every optional filter call
- Avoid forwarding unmapped DTO fields directly into builders
- Test suspension filter paths with non-suspended data
When it happens
Trigger: Calling createPlanItemInstanceQuery().planItemInstanceLastSuspendedBefore(null), typically when suspension timestamps were never tracked or a DTO field is unset.
Common situations: Queries against plan items that were never suspended, where a 'last suspended' lookup yields null; optional filters from REST payloads; refactor renaming local variables leaving null initializers.
Related errors
- activatedBefore is null
- completedBefore is null
- disabledAfter is null
- disabledBefore is null
- enabledAfter is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/275b5d9914eeb37a.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java:493
}
@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;
}
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;View on GitHub (pinned to d6d39ce1c6)