flowable/flowable-engine · error · FlowableIllegalArgumentException
state is null
Error message
state is null
What it means
HistoricCaseInstanceQueryImpl.state() is a query-builder setter for the case instance state (e.g. 'active', 'completed', 'terminated'). The Flowable CMMN engine throws FlowableIllegalArgumentException immediately when the argument is null because a null state can never be translated into a meaningful SQL predicate. This is fail-fast input validation, not a runtime failure of the engine.
Solutions
- Ensure a non-null state value (e.g. "active", "completed", "terminated") is passed to state().
- If the state filter is optional, skip calling state() entirely instead of calling it with null.
- Validate/sanitize the input (e.g. map empty or 'any' UI values to skipping the filter) before building the query.
- Catch FlowableIllegalArgumentException if input is user-supplied and return a 400-style validation message.
Example fix
// before
String state = request.getParameter("state"); // may be null
query.state(state);
// after
String state = request.getParameter("state");
if (state != null && !state.isEmpty()) {
query.state(state);
} Defensive patterns
Strategy: validation
Validate before calling
if (state != null) {
query.state(state);
} Type guard
boolean hasState = s -> s != null && !s.trim().isEmpty();
Try / catch
try {
query.state(state);
} catch (FlowableIllegalArgumentException e) {
throw new IllegalArgumentException("Invalid state filter: " + e.getMessage());
} Prevention
- Treat state() as optional: only call it when a concrete state is selected.
- Centralize query building in a helper that skips null filters.
- Validate UI/request inputs at the boundary (non-empty, allowed values: active/completed/terminated).
- Never rely on the engine to null-check user input.
When it happens
Trigger: Calling historicCaseInstanceQuery.state(null) directly, or passing a variable that resolves to null (e.g. an unset request parameter or config value) into state().
Common situations: Web/UI code binding a state filter from a request parameter that was never supplied; deserializing query options from JSON where the state key is absent; refactoring where a constant holding the state became null.
Related errors
- callbackId is null
- Parent id is null
- Provided sub scope id is null
- user id is null
- activatedBefore is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2557911558e541bc.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java:676
@Override
public HistoricCaseInstanceQueryImpl finishedBy(String userId) {
if (userId == null) {
throw new FlowableIllegalArgumentException("user id is null");
}
if (inOrStatement) {
this.currentOrQueryObject.finishedBy = userId;
} else {
this.finishedBy = userId;
}
return this;
}
@Override
public HistoricCaseInstanceQueryImpl state(String state) {
if (state == null) {
throw new FlowableIllegalArgumentException("state is null");
}
if (inOrStatement) {
this.currentOrQueryObject.state = state;
} else {
this.state = state;
}
return this;
}
@Override
public HistoricCaseInstanceQuery lastReactivatedBefore(Date beforeTime) {
if (beforeTime == null) {
throw new FlowableIllegalArgumentException("before time is null");
}
if (inOrStatement) {
this.currentOrQueryObject.lastReactivatedBefore = beforeTime;
} else {View on GitHub (pinned to d6d39ce1c6)