flowable/flowable-engine · error · FlowableIllegalArgumentException
Booleans and null cannot be used in 'greater than' condition
Error message
Booleans and null cannot be used in 'greater than' condition
What it means
Flowable variable queries reject null and Boolean values for GREATER_THAN operators, because neither can be meaningfully ordered in SQL variable comparisons. The check lives in AbstractVariableQueryImpl.addVariable, the shared validation path for all variable query value setters. It is thrown as FlowableIllegalArgumentException at query-construction time, before any database call.
Solutions
- Use EQUALS/NOT_EQUALS (or EXISTS/NOT_EXISTS for null) instead of a greater-than operator for null or boolean values
- Change the variable to a comparable type (number, date, string) if ordering semantics are needed
- Guard the call site: only invoke greaterThan setters when the value is non-null and not Boolean
- Use in-memory filtering of query results when boolean/null ordering logic is truly required
Example fix
// before
historyService.createHistoricVariableInstanceQuery()
.variableValueGreaterThan("active", true);
// after
historyService.createHistoricVariableInstanceQuery()
.variableValueEquals("active", true); Defensive patterns
Strategy: validation
Validate before calling
if (value == null || value instanceof Boolean) {
throw new IllegalArgumentException("Use equals/exists operators for null or boolean variable values");
}
query.variableValueGreaterThan(name, value); Type guard
static boolean isComparableVarValue(Object v) {
return v != null && !(v instanceof Boolean);
} Try / catch
try {
query.variableValueGreaterThan(name, value);
} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {
// fall back to equals or log and skip clause
} Prevention
- Never pass Boolean or null to greaterThan/greaterThanOrEqual setters
- Use variableValueEquals for booleans and variableValueExists for null checks
- Validate value types in query-builder helper methods
- Document variable types at design time to match query operators
When it happens
Trigger: Calling any of taskVariableValueGreaterThan / processVariableValueGreaterThan / scopedVariableValueGreaterThan (or the variants routed through addVariable) with value=null or a Boolean, e.g. queryVariableValueGreaterThan("flag", true).
Common situations: Passing a Boolean flag to numeric comparison APIs; passing null intending 'any value'; auto-generating queries from maps that contain nulls or booleans; migrating code from EQUALS queries to GREATER_THAN without revisiting value types.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Booleans and null cannot be used in 'less than' condition
- appsDefinitionIds is null
- Booleans and null cannot be used in 'greater than or equal'…
- Booleans and null cannot be used in 'less than or equal'…
- Business status is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/cca4eb9d27b0e59a.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/AbstractVariableQueryImpl.java:307
@SuppressWarnings("unchecked")
protected T scopedVariableNotExists(String name, String scopeType) {
addVariable(name, null, QueryOperator.NOT_EXISTS, scopeType, false);
return (T) this;
}
protected void addVariable(String name, Object value, QueryOperator operator, boolean localScope) {
this.addVariable(name, value, operator, null, localScope);
}
protected void addVariable(String name, Object value, QueryOperator operator, String scopeType, boolean localScope) {
if (name == null) {
throw new FlowableIllegalArgumentException("name is null");
}
if (value == null || isBoolean(value)) {
// Null-values and booleans can only be used in EQUALS, NOT_EQUALS, EXISTS and NOT_EXISTS
switch (operator) {
case GREATER_THAN:
throw new FlowableIllegalArgumentException("Booleans and null cannot be used in 'greater than' condition");
case LESS_THAN:
throw new FlowableIllegalArgumentException("Booleans and null cannot be used in 'less than' condition");
case GREATER_THAN_OR_EQUAL:
throw new FlowableIllegalArgumentException("Booleans and null cannot be used in 'greater than or equal' condition");
case LESS_THAN_OR_EQUAL:
throw new FlowableIllegalArgumentException("Booleans and null cannot be used in 'less than or equal' condition");
default:
break;
}
if (operator == QueryOperator.EQUALS_IGNORE_CASE && !(value instanceof String)) {
throw new FlowableIllegalArgumentException("Only string values can be used with 'equals ignore case' condition");
}
if (operator == QueryOperator.NOT_EQUALS_IGNORE_CASE && !(value instanceof String)) {
throw new FlowableIllegalArgumentException("Only string values can be used with 'not equals ignore case' condition");
}
View on GitHub (pinned to d6d39ce1c6)