{"record":{"id":"458631eb788145d8","repo":"flowable/flowable-engine","slug":"condition-script-returns-null-expression","errorCode":null,"errorMessage":"condition script returns null: ${expression}","messagePattern":"condition script returns null: (.+?)","errorType":"exception","errorClass":"org.activiti.engine.ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/scripting/ScriptCondition.java","lineNumber":55,"sourceCode":"    }\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(expression, DynamicBpmnConstants.SEQUENCE_FLOW_CONDITION, elementProperties);\n        } else {\n            conditionExpression = expression;\n        }\n\n        ScriptingEngines scriptingEngines = Context\n                .getProcessEngineConfiguration()\n                .getScriptingEngines();\n\n        Object result = scriptingEngines.evaluate(conditionExpression, language, execution);\n        if (result == null) {\n            throw new ActivitiException(\"condition script returns null: \" + expression);\n        }\n        if (!(result instanceof Boolean)) {\n            throw new ActivitiException(\"condition script returns non-Boolean: \" + 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":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/scripting/ScriptCondition.java#L37-L73","documentation":"ScriptCondition.evaluate runs the condition expression through the ScriptingEngines for the configured language. If the script evaluates to null the condition cannot be interpreted as true/false, so an ActivitiException is thrown including the original expression text.","triggerScenarios":"A sequence-flow condition script (e.g. a Groovy/JS condition on a flow) whose last statement evaluates to null or has no return value — commonly a script that performs an action but never returns a value.","commonSituations":"Groovy/JavaScript scripts that forget 'return', scripts whose final expression is a void method call, dynamic language returning undefined (JS) instead of a boolean, condition script delegating to a bean method returning null.","solutions":["Ensure the condition script explicitly returns a boolean (add 'return' where the language requires it).","Check the script's last statement actually produces a value rather than calling a void method.","If using JavaScript, return explicit true/false instead of relying on truthy/falsy or undefined values.","Verify the delegated bean/method used in the expression cannot return null."],"exampleFix":"// before (Groovy condition)\n${orderService.checkApproved(execution)} // void or null-returning\n// after\n${return orderService.isApproved(execution)}","handlingStrategy":"validation","validationCode":"// audit condition scripts before deployment\nif (!conditionScript.matches(\"(?s).*\\\\breturn\\\\b.*\")) {\n    throw new IllegalArgumentException(\"condition script must return a value: \" + conditionScript);\n}","typeGuard":null,"tryCatchPattern":"try {\n    conditionResult = ScriptCondition.evaluate(...);\n} catch (ActivitiException e) {\n    if (e.getMessage().contains(\"returns null\")) {\n        throw new InvalidConditionException(\"fix the script to return a boolean\");\n    }\n    throw e;\n}","preventionTips":["Always write condition scripts with an explicit 'return <boolean>' statement.","Avoid void method calls as the last statement of a condition script.","Unit-test sequence flow conditions before deploying the process."],"tags":["scripting","condition","null","bpmn"],"backgroundTag":"null-argument","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"}