flowable/flowable-engine · error · FlowableException

condition expression returns non-Boolean (elementId: " +…

Error message

condition expression returns non-Boolean (elementId: " + elementId + "): " + result + " (" + result.getClass().getName() + ") for " + execution

What it means

Thrown by UelExpressionCondition.evaluate when a condition expression evaluates to a non-Boolean value. BPMN conditional flows require a strict Boolean result; any other type (String, Integer, etc.) cannot be used to decide the branch, so the engine throws and includes the actual value and its class name.

Solutions

  1. Convert the value to a real Boolean: set the variable as java.lang.Boolean instead of String.
  2. Make the expression return a Boolean, e.g. ${approved == 'true'} or ${Boolean.parseBoolean(approved)} instead of ${approved}.
  3. Read the class name in the message to identify the offending type, then fix the variable set on the execution.
  4. If the value comes from a form/API, normalize it to boolean before passing to startProcessInstance or setVariable.

Example fix

// before
vars.put("approved", "true"); // String
// after
vars.put("approved", Boolean.TRUE);
Defensive patterns

Strategy: type-guard

Validate before calling

Object approved = vars.get("approved");
if (!(approved instanceof Boolean)) {
    throw new IllegalArgumentException("approved must be Boolean, got " + (approved == null ? null : approved.getClass()));
}

Type guard

boolean isBoolVar(Map<String, Object> vars, String name) {
    return vars.get(name) instanceof Boolean;
}

Try / catch

try {
    runtimeService.startProcessInstanceByKey(key, vars);
} catch (FlowableException e) {
    if (e.getMessage().contains("condition expression returns non-Boolean")) {
        // normalize the variable type named in the message and retry
    }
}

Prevention

When it happens

Trigger: evaluate(elementId, execution) where expression.getValue(execution) returns a non-Boolean, e.g. conditionExpression '${approved}' where variable approved is a String "true" instead of boolean, or an expression like ${count} resolving to an Integer, or an EL method returning a non-boolean type.

Common situations: Variables set as Strings from JSON/forms but used directly in conditions; expressions like ${var == 'x'} accidentally written as ${var} with a String value; returning wrong type from a bean method; languages/data sources where booleans serialize as 'true'/'false' strings.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/el/UelExpressionCondition.java:43

 * @author Frederik Heremans
 */
public class UelExpressionCondition implements Condition {

    protected Expression expression;

    public UelExpressionCondition(Expression expression) {
        this.expression = expression;
    }

    @Override
    public boolean evaluate(String elementId, DelegateExecution execution) {
        Object result = expression.getValue(execution);

        if (result == null) {
            throw new FlowableException("condition expression returns null (elementId: " + elementId + ") for " + execution);
        }
        if (!(result instanceof Boolean)) {
            throw new FlowableException("condition expression returns non-Boolean (elementId: " + elementId + "): " + result + " (" + result.getClass().getName() + ") for " + execution);
        }
        return (Boolean) result;
    }

}

View on GitHub (pinned to d6d39ce1c6)