flowable/flowable-engine · error · FlowableIllegalArgumentException

Booleans and null cannot be used in 'less than or equal'…

Error message

Booleans and null cannot be used in 'less than or equal' condition

What it means

LESS_THAN_OR_EQUAL comparisons cannot be combined with null or Boolean variable values in Flowable, because such values have no defined ordering. The validation in AbstractVariableQueryImpl.addVariable throws FlowableIllegalArgumentException as soon as the clause is registered. This is a programming/API-usage error, not an environment issue.

Solutions

  1. Pass only non-null comparable values (numbers, dates, strings) to lessThanOrEqual
  2. Use variableValueEquals for boolean conditions and variableValueExists for null checks
  3. Add a caller-side check: skip the clause or use EQUALS when value is null/Boolean
  4. Re-model the variable to store a comparable type

Example fix

// before
q.variableValueLessThanOrEqual("done", Boolean.TRUE);
// after
q.variableValueEquals("done", Boolean.TRUE);
Defensive patterns

Strategy: validation

Validate before calling

if (value == null || value instanceof Boolean) {
    throw new IllegalArgumentException("LessThanOrEqual requires a non-null non-boolean value");
}
query.variableValueLessThanOrEqual(name, value);

Type guard

static boolean canOrder(Object v) {
    return v != null && !(v instanceof Boolean);
}

Try / catch

try {
    query.variableValueLessThanOrEqual(name, value);
} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {
    // use equals or omit condition
}

Prevention

When it happens

Trigger: Any variable query builder call that reaches addVariable with operator LESS_THAN_OR_EQUAL and a null or Boolean value, e.g. processVariableValueLessThanOrEqual("retry", true).

Common situations: Treating boolean columns as numeric thresholds; null coming from an unset date bound; reflection-based query builders forwarding raw Object values.

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


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

Appendix: source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/AbstractVariableQueryImpl.java:313

    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");
            }

            if ((operator == QueryOperator.LIKE || operator == QueryOperator.LIKE_IGNORE_CASE) && !(value instanceof String)) {
                throw new FlowableIllegalArgumentException("Only string values can be used with 'like' condition");
            }
        }

        queryVariableValues.add(new QueryVariableValue(name, value, operator, localScope, scopeType));

View on GitHub (pinned to d6d39ce1c6)