flowable/flowable-engine · error · FlowableException
condition expression returns non-Boolean (elementId: " + ele
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.
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)
Solutions
- Convert the value to a real Boolean: set the variable as java.lang.Boolean instead of String.
- Make the expression return a Boolean, e.g. ${approved == 'true'} or ${Boolean.parseBoolean(approved)} instead of ${approved}.
- Read the class name in the message to identify the offending type, then fix the variable set on the execution.
- 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
- Store booleans as Boolean, never as "true"/"false" Strings.
- Keep condition expressions strictly Boolean-producing.
- Validate form/API payloads for boolean-typed variables before submission.
- Add deployment-time checks or tests that evaluate each conditionExpression with sample variables.
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
- condition expression returns null (elementId: " + elementId
- ${collectionExpressionText}' didn't resolve to a Collection
- Variable ${collectionVariable}' is not a Collection
- Expected LambdaExpression but got: " + (lambdaObj == null ?
- Cannot coerce property to array index:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/2635c79951d59f0d.
Report an issue: GitHub.