{"record":{"id":"ce58750d3730d3be","repo":"flowable/flowable-engine","slug":"condition-expression-returns-null-sequenceflowid","errorCode":null,"errorMessage":"condition expression returns null (sequenceFlowId: ${sequenceFlowId})","messagePattern":"condition expression returns null \\(sequenceFlowId: (.+?)\\)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/el/UelExpressionCondition.java","lineNumber":56,"sourceCode":"    public UelExpressionCondition(String conditionExpression) {\n        this.initialConditionExpression = conditionExpression;\n    }\n\n    @Override\n    public boolean evaluate(String sequenceFlowId, DelegateExecution execution) {\n        String conditionExpression = null;\n        if (Context.getProcessEngineConfiguration().isEnableProcessDefinitionInfoCache()) {\n            ObjectNode elementProperties = Context.getBpmnOverrideElementProperties(sequenceFlowId, execution.getProcessDefinitionId());\n            conditionExpression = getActiveValue(initialConditionExpression, DynamicBpmnConstants.SEQUENCE_FLOW_CONDITION, elementProperties);\n        } else {\n            conditionExpression = initialConditionExpression;\n        }\n\n        Expression expression = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(conditionExpression);\n        Object result = expression.getValue(execution);\n\n        if (result == null) {\n            throw new ActivitiException(\"condition expression returns null (sequenceFlowId: \" + sequenceFlowId + \")\" );\n        }\n        if (!(result instanceof Boolean)) {\n            throw new ActivitiException(\"condition expression returns non-Boolean (sequenceFlowId: \" + sequenceFlowId + \"): \" + result + \" (\" + result.getClass().getName() + \")\");\n        }\n        return (Boolean) result;\n    }\n\n    protected String getActiveValue(String originalValue, String propertyName, ObjectNode elementProperties) {\n        String activeValue = originalValue;\n        if (elementProperties != null) {\n            JsonNode overrideValueNode = elementProperties.get(propertyName);\n            if (overrideValueNode != null) {\n                if (overrideValueNode.isNull()) {\n                    activeValue = null;\n                } else {\n                    activeValue = overrideValueNode.asString();\n                }\n            }","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/el/UelExpressionCondition.java#L38-L74","documentation":"UelExpressionCondition evaluates a sequence-flow condition expression for gateway/flow routing. Flowable requires a Boolean answer to decide routing; if the expression evaluates to null it throws ActivitiException because the condition cannot be resolved.","triggerScenarios":"A sequence flow's conditionExpression evaluates to null — e.g. the expression references a missing/empty variable (${approved == null} not used, instead the whole expression returns null) or a method returning void/null.","commonSituations":"Exclusive/inclusive gateway conditions calling beans whose methods return null; expressions typed against variables that are not set; copy-pasted conditions that aren't boolean.","solutions":["Fix the condition expression to always return a boolean, e.g. ${approved == true} or wrap in Boolean()","Ensure the bean method or variable referenced returns a Boolean, never null","Set the referenced variable before the gateway executes"],"exampleFix":"// before\n<conditionExpression xsi:type=\"tFormalExpression\">${myBean.check()}</conditionExpression>\n// after (bean returns boolean)\n<conditionExpression xsi:type=\"tFormalExpression\">${myBean.check() == true}</conditionExpression>","handlingStrategy":"validation","validationCode":"Expression e = Context.getProcessEngineConfiguration().getExpressionManager()\n        .createExpression(cond);\nObject r = e.getValue(execution);\nif (r == null || !(r instanceof Boolean)) {\n    throw new IllegalArgumentException(\"Condition must evaluate to Boolean: \" + cond);\n}","typeGuard":"boolean isBooleanResult(Object r) {\n    return r instanceof Boolean;\n}","tryCatchPattern":"try {\n    flowTaken = condition.evaluate(execution, flowId);\n} catch (ActivitiException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"returns null\")) {\n        // ensure referenced variable/bean returns a boolean\n    }\n}","preventionTips":["Make every sequence-flow condition a boolean expression","Ensure bean methods used in conditions return Boolean, never null","Set all variables referenced by gateway conditions before the gateway executes"],"tags":["expression-language","condition","gateway","null"],"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"}