flowable/flowable-engine · error · FlowableIllegalArgumentException
availableAfter is null
Error message
availableAfter is null
What it means
Thrown by PlanItemInstanceQueryImpl.planItemInstanceLastAvailableAfter when the availableAfter Date is null. Like other date filters, a null lower bound is rejected at query-construction time to keep the generated SQL well-defined.
Solutions
- Pass a valid java.util.Date for the bound.
- Guard with a null check and omit the filter when absent.
- Ensure the date deserializer/parser returns an error instead of null for malformed input.
Example fix
// before
query.planItemInstanceLastAvailableAfter(from); // from may be null
// after
if (from != null) {
query.planItemInstanceLastAvailableAfter(from);
} Defensive patterns
Strategy: validation
Validate before calling
if (availableAfter != null) {
planItemInstanceQuery.planItemInstanceLastAvailableAfter(availableAfter);
} Type guard
boolean isPresent(Date d) {
return d != null;
} Try / catch
try {
query.planItemInstanceLastAvailableAfter(availableAfter);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().contains("availableAfter is null")) {
// rebuild the query without this bound
} else {
throw e;
}
} Prevention
- Only apply date filters when the bound is present
- Validate 'from'/'to' parameters at the controller layer
- Use strict date parsing to avoid silent nulls
When it happens
Trigger: Calling planItemInstanceLastAvailableAfter(null), usually from an absent 'from' timestamp or a failed date parse.
Common situations: Reporting windows with optional start dates; deserialization of a missing JSON date field into null.
Related errors
- availableBefore is null
- createdAfter is null
- createdBefore is null
- unavailableBefore is null
- activatedBefore is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/fda57b0da620de93.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java:376
}
@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;
}
return this;
}
@Override
public PlanItemInstanceQuery planItemInstanceLastAvailableAfter(Date availableAfter) {
if (availableAfter == null) {
throw new FlowableIllegalArgumentException("availableAfter is null");
}
if (inOrStatement) {
this.currentOrQueryObject.lastAvailableAfter = availableAfter;
} else {
this.lastAvailableAfter = availableAfter;
}
return this;
}
@Override
public PlanItemInstanceQuery planItemInstanceLastUnavailableBefore(Date unavailableBefore) {
if (unavailableBefore == null) {
throw new FlowableIllegalArgumentException("unavailableBefore is null");
}
if (inOrStatement) {
this.currentOrQueryObject.lastUnavailableBefore = unavailableBefore;
} else {
this.lastUnavailableBefore = unavailableBefore;View on GitHub (pinned to d6d39ce1c6)