{"record":{"id":"cca4eb9d27b0e59a","repo":"flowable/flowable-engine","slug":"booleans-and-null-cannot-be-used-in-greater-than","errorCode":null,"errorMessage":"Booleans and null cannot be used in 'greater than' condition","messagePattern":"Booleans and null cannot be used in 'greater than' condition","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/AbstractVariableQueryImpl.java","lineNumber":307,"sourceCode":"    @SuppressWarnings(\"unchecked\")\n    protected T scopedVariableNotExists(String name, String scopeType) {\n        addVariable(name, null, QueryOperator.NOT_EXISTS, scopeType, false);\n        return (T) this;\n    }\n\n    protected void addVariable(String name, Object value, QueryOperator operator, boolean localScope) {\n        this.addVariable(name, value, operator, null, localScope);\n    }\n\n    protected void addVariable(String name, Object value, QueryOperator operator, String scopeType, boolean localScope) {\n        if (name == null) {\n            throw new FlowableIllegalArgumentException(\"name is null\");\n        }\n        if (value == null || isBoolean(value)) {\n            // Null-values and booleans can only be used in EQUALS, NOT_EQUALS, EXISTS and NOT_EXISTS\n            switch (operator) {\n                case GREATER_THAN:\n                    throw new FlowableIllegalArgumentException(\"Booleans and null cannot be used in 'greater than' condition\");\n                case LESS_THAN:\n                    throw new FlowableIllegalArgumentException(\"Booleans and null cannot be used in 'less than' condition\");\n                case GREATER_THAN_OR_EQUAL:\n                    throw new FlowableIllegalArgumentException(\"Booleans and null cannot be used in 'greater than or equal' condition\");\n                case LESS_THAN_OR_EQUAL:\n                    throw new FlowableIllegalArgumentException(\"Booleans and null cannot be used in 'less than or equal' condition\");\n                default:\n                    break;\n            }\n\n            if (operator == QueryOperator.EQUALS_IGNORE_CASE && !(value instanceof String)) {\n                throw new FlowableIllegalArgumentException(\"Only string values can be used with 'equals ignore case' condition\");\n            }\n\n            if (operator == QueryOperator.NOT_EQUALS_IGNORE_CASE && !(value instanceof String)) {\n                throw new FlowableIllegalArgumentException(\"Only string values can be used with 'not equals ignore case' condition\");\n            }\n","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/AbstractVariableQueryImpl.java#L289-L325","documentation":"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.","triggerScenarios":"Calling any of taskVariableValueGreaterThan / processVariableValueGreaterThan / scopedVariableValueGreaterThan (or the variants routed through addVariable) with value=null or a Boolean, e.g. queryVariableValueGreaterThan(\"flag\", true).","commonSituations":"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.","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"],"exampleFix":"// before\nhistoryService.createHistoricVariableInstanceQuery()\n    .variableValueGreaterThan(\"active\", true);\n// after\nhistoryService.createHistoricVariableInstanceQuery()\n    .variableValueEquals(\"active\", true);","handlingStrategy":"validation","validationCode":"if (value == null || value instanceof Boolean) {\n    throw new IllegalArgumentException(\"Use equals/exists operators for null or boolean variable values\");\n}\nquery.variableValueGreaterThan(name, value);","typeGuard":"static boolean isComparableVarValue(Object v) {\n    return v != null && !(v instanceof Boolean);\n}","tryCatchPattern":"try {\n    query.variableValueGreaterThan(name, value);\n} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {\n    // fall back to equals or log and skip clause\n}","preventionTips":["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"],"tags":["flowable","validation","query","boolean"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}