flowable/flowable-engine · error · FlowableIllegalArgumentException

exitBefore is null

Error message

exitBefore is null

What it means

Flowable throws FlowableIllegalArgumentException when planItemInstanceExitBefore(Date) receives a null Date. Eager validation guarantees that only well-formed timestamp criteria enter the query. To skip this filter, do not call the method.

Solutions

  1. Pass a non-null Date derived from validated input.
  2. Guard the call site and omit the criterion when the value is null.
  3. Parse string dates with explicit error handling before building the query.
  4. Wrap query construction in try-catch for FlowableIllegalArgumentException to fail fast.

Example fix

// before
query.planItemInstanceExitBefore(criteria.getExitBefore()); // may be null
// after
if (criteria.getExitBefore() != null) {
    query.planItemInstanceExitBefore(criteria.getExitBefore());
}
Defensive patterns

Strategy: validation

Validate before calling

if (exitBefore == null) {
    throw new IllegalArgumentException("exitBefore must be non-null; omit the filter instead");
}
query.planItemInstanceExitBefore(exitBefore);

Type guard

boolean hasExitBefore = (exitBefore != null);

Try / catch

try {
    query.planItemInstanceExitBefore(exitBefore);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("exitBefore")) {
        throw new BadRequestException("exitBefore date filter must not be null");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling createPlanItemInstanceQuery().planItemInstanceExitBefore(null), typically when the exit-before date comes from an optional request parameter left unset.

Common situations: Empty 'exitBefore' field in a case-management search screen; absent JSON property; null result of date parsing of user input.

Related errors


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

Appendix: source

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

    }

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

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

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

View on GitHub (pinned to d6d39ce1c6)