{"record":{"id":"008858708590dc2f","repo":"flowable/flowable-engine","slug":"no-execution-context-available","errorCode":null,"errorMessage":"no execution context available","messagePattern":"no execution context available","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/RuleEngineExecutorImpl.java","lineNumber":115,"sourceCode":"            executionContext.getAuditContainer().setExceptionMessage(getExceptionMessage(fe));\n\n        } finally {\n            // end audit trail\n            executionContext.getAuditContainer().stopAudit(dmnEngineConfiguration.getClock().getCurrentTime());\n        }\n\n        return executionContext.getAuditContainer();\n    }\n\n    protected void evaluateDecisionTable(DecisionTable decisionTable, ELExecutionContext executionContext) {\n        if (decisionTable == null || decisionTable.getRules().isEmpty()) {\n            throw new IllegalArgumentException(\"no rules present in table\");\n        }\n\n        LOGGER.debug(\"Start table evaluation: {}\", decisionTable.getId());\n\n        if (executionContext == null) {\n            throw new FlowableException(\"no execution context available\");\n        }\n\n        try {\n            // evaluate rule conditions\n            Map<Integer, List<RuleOutputClauseContainer>> validRuleOutputEntries = new HashMap<>();\n\n            for (DecisionRule rule : decisionTable.getRules()) {\n                boolean ruleResult = executeRule(rule, executionContext);\n\n                if (ruleResult) {\n                    // evaluate decision table hit policy validity\n                    if (getHitPolicyBehavior(decisionTable.getHitPolicy()) instanceof EvaluateRuleValidityBehavior) {\n                        ((EvaluateRuleValidityBehavior) getHitPolicyBehavior(decisionTable.getHitPolicy())).evaluateRuleValidity(rule.getRuleNumber(), executionContext);\n                    }\n\n                    // add valid rule output(s)\n                    validRuleOutputEntries.put(rule.getRuleNumber(), rule.getOutputEntries());\n                }","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/RuleEngineExecutorImpl.java#L97-L133","documentation":"evaluateDecisionTable requires a non-null ELExecutionContext to evaluate expressions and record the audit trail. When the passed context is null it throws FlowableException(\"no execution context available\") (RuleEngineExecutorImpl.java:114-116). In the default flow execute() builds the context via ELExecutionContextBuilder.build so this only fires when build returns null (e.g. a broken custom builder) or when evaluateDecisionTable is invoked directly with a null context. Unlike the IllegalArgumentException guards, this FlowableException is caught by execute() and recorded on the audit container as a failed decision.","triggerScenarios":"Subclassing RuleEngineExecutorImpl / overriding ELExecutionContextBuilder so build() yields null; calling the protected evaluateDecisionTable(table, null) directly from custom code; any path where execute()'s context construction is bypassed or stubbed in tests.","commonSituations":"Unit tests mocking ELExecutionContextBuilder.build to return null, custom DMN engine configuration that replaces the context builder, or reflective/internal calls into evaluateDecisionTable without a proper context.","solutions":["Ensure ELExecutionContextBuilder.build returns a valid context — check your DmnEngineConfiguration and any custom builder overrides.","In tests, construct a real ELExecutionContext (via ELExecutionContextBuilder.build(decision, executeDecisionInfo)) instead of passing/mock-returning null.","If calling evaluateDecisionTable directly, always build the context first.","Catch FlowableException around execute() and inspect the audit container's exceptionMessage if you want graceful failure handling."],"exampleFix":"// before\nruleEngineExecutor.evaluateDecisionTable(table, null); // FlowableException\n// after\nELExecutionContext ctx = ELExecutionContextBuilder.build(decision, executeDecisionInfo);\nruleEngineExecutor.evaluateDecisionTable(table, ctx);","handlingStrategy":"validation","validationCode":"ELExecutionContext ctx = ELExecutionContextBuilder.build(decision, executeDecisionInfo);\nif (ctx == null) {\n    throw new IllegalStateException(\"ELExecutionContextBuilder returned null; check custom builder/engine configuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    audit = ruleEngineExecutor.execute(decision, executeDecisionInfo);\n} catch (FlowableException fe) {\n    log.error(\"DMN execution failed: {}\", fe.getMessage(), fe);\n    audit = null; // or fall back\n}","preventionTips":["Do not stub ELExecutionContextBuilder.build to return null in tests; build a real context.","Review custom DmnEngineConfiguration for overrides that could break context creation.","Call execute() rather than the protected evaluateDecisionTable directly."],"tags":["dmn","java","null-check","internal-state"],"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"}