{"record":{"id":"8f8bde58b629558a","repo":"flowable/flowable-engine","slug":"condition-expression-returns-null-elementid","errorCode":null,"errorMessage":"condition expression returns null (elementId: \" + elementId + \") for \" + execution","messagePattern":"condition expression returns null \\(elementId: \" \\+ elementId \\+ \"\\) for \" \\+ execution","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/el/UelExpressionCondition.java","lineNumber":40,"sourceCode":" * {@link Condition} that resolves an UEL expression at runtime.\n * \n * @author Joram Barrez\n * @author Frederik Heremans\n */\npublic class UelExpressionCondition implements Condition {\n\n    protected Expression expression;\n\n    public UelExpressionCondition(Expression expression) {\n        this.expression = expression;\n    }\n\n    @Override\n    public boolean evaluate(String elementId, DelegateExecution execution) {\n        Object result = expression.getValue(execution);\n\n        if (result == null) {\n            throw new FlowableException(\"condition expression returns null (elementId: \" + elementId + \") for \" + execution);\n        }\n        if (!(result instanceof Boolean)) {\n            throw new FlowableException(\"condition expression returns non-Boolean (elementId: \" + elementId + \"): \" + result + \" (\" + result.getClass().getName() + \") for \" + execution);\n        }\n        return (Boolean) result;\n    }\n\n}\n","sourceCodeStart":22,"sourceCodeEnd":49,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/el/UelExpressionCondition.java#L22-L49","documentation":"Thrown by UelExpressionCondition.evaluate when a condition expression (e.g. a conditional sequence-flow ${...} expression) evaluates to null. The engine requires a definite Boolean verdict to route execution; null gives no routing information, so the engine fails fast instead of guessing a branch.","triggerScenarios":"Calling evaluate(elementId, execution) where expression.getValue(execution) returns null. Typical API path: process runtime reaching an inclusive/exclusive gateway or conditional flow whose conditionExpression resolves to nothing - e.g. expression ${orderStatus == 'OK'} where variable orderStatus is unset (juel resolves to null), or an expression returning null explicitly.","commonSituations":"Process variables not set before the gateway (deployed process expects a variable the caller never passes); typos in variable names inside EL expressions; Spring/CDN bean lookups in expressions resolving to null; migrations where a variable was renamed; returning null from a delegateBean method used in the condition.","solutions":["Set the process variable referenced by the condition before execution reaches the conditional flow (runtimeService.setVariable(executionId, ...) or pass it at startProcessInstanceBy...).","Make the condition null-safe, e.g. ${orderStatus != null && orderStatus == 'OK'}.","Give the gateway a default flow so unset conditions route predictably (though the null verdict still throws - fixing the variable is required).","Log/check which variable is missing: parse elementId from the message and inspect the process XML for the conditionExpression on that flow element."],"exampleFix":"// before: expression references missing variable\n<conditionExpression xsi:type=\"tFormalExpression\">${order.status == 'APPROVED'}</conditionExpression>\n// after: null-safe expression + guaranteed variable\n<conditionExpression xsi:type=\"tFormalExpression\">${order != null &amp;&amp; order.status == 'APPROVED'}</conditionExpression>\n// and in Java: runtimeService.startProcessInstanceByKey(\"order\", vars) with vars.put(\"order\", order)","handlingStrategy":"validation","validationCode":"// before starting/completing tasks that reach conditional flows\nif (vars.get(\"orderStatus\") == null) {\n    throw new IllegalStateException(\"orderStatus must be set before gateway\");\n}","typeGuard":"Object v = execution.getVariable(\"orderStatus\");\nif (v instanceof String && ((String) v).isEmpty()) {\n    throw new IllegalArgumentException(\"orderStatus empty\");\n}","tryCatchPattern":"try {\n    taskService.complete(taskId, vars);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"condition expression returns null\")) {\n        // set missing variable and retry\n    }\n}","preventionTips":["Always put process variables required by conditions in the start/complete variable map.","Write null-safe EL expressions (${x != null && ...}).","Model default flows on exclusive gateways.","Add a unit test that walks each conditional flow with expected variable sets."],"tags":["bpmn","expression-language","process-engine","null-value"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}