{"record":{"id":"ceba7cbf5e20c8b0","repo":"flowable/flowable-engine","slug":"executedecisioncontext-is-null","errorCode":null,"errorMessage":"ExecuteDecisionContext is null","messagePattern":"ExecuteDecisionContext is null","errorType":"exception","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/cmd/PersistHistoricDecisionExecutionCmd.java","lineNumber":44,"sourceCode":"import tools.jackson.databind.ObjectMapper;\r\nimport tools.jackson.databind.json.JsonMapper;\r\n\r\n/**\r\n * @author Yvo Swillens\r\n */\r\npublic class PersistHistoricDecisionExecutionCmd implements Command<Void> {\r\n\r\n    protected ExecuteDecisionContext executeDecisionContext;\r\n\r\n    public PersistHistoricDecisionExecutionCmd(ExecuteDecisionContext executeDecisionContext) {\r\n        this.executeDecisionContext = executeDecisionContext;\r\n    }\r\n\r\n    @Override\r\n    public Void execute(CommandContext commandContext) {\r\n\r\n        if (executeDecisionContext == null) {\r\n            throw new FlowableIllegalArgumentException(\"ExecuteDecisionContext is null\");\r\n        }\r\n\r\n        DmnEngineConfiguration engineConfiguration = CommandContextUtil.getDmnEngineConfiguration();\r\n\r\n        if (engineConfiguration.isHistoryEnabled()) {\r\n            HistoricDecisionExecutionEntityManager historicDecisionExecutionEntityManager = engineConfiguration.getHistoricDecisionExecutionEntityManager();\r\n            HistoricDecisionExecutionEntity decisionExecutionEntity = historicDecisionExecutionEntityManager.create();\r\n            decisionExecutionEntity.setDecisionDefinitionId(executeDecisionContext.getDecisionId());\r\n            decisionExecutionEntity.setDeploymentId(executeDecisionContext.getDeploymentId());\r\n            decisionExecutionEntity.setStartTime(executeDecisionContext.getDecisionExecution().getStartTime());\r\n            decisionExecutionEntity.setEndTime(executeDecisionContext.getDecisionExecution().getEndTime());\r\n            decisionExecutionEntity.setInstanceId(executeDecisionContext.getInstanceId());\r\n            decisionExecutionEntity.setExecutionId(executeDecisionContext.getExecutionId());\r\n            decisionExecutionEntity.setActivityId(executeDecisionContext.getActivityId());\r\n            decisionExecutionEntity.setScopeType(executeDecisionContext.getScopeType());\r\n            decisionExecutionEntity.setTenantId(executeDecisionContext.getTenantId());\r\n\r\n            Boolean failed = executeDecisionContext.getDecisionExecution().isFailed();\r","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/cmd/PersistHistoricDecisionExecutionCmd.java#L26-L62","documentation":"PersistHistoricDecisionExecutionCmd persists a historic decision execution record using the ExecuteDecisionContext supplied to its constructor. If that context is null the command throws FlowableIllegalArgumentException, because it cannot derive the decision execution data to store. It is invoked from the ExecuteDecisionActivityBehavior during DMN rule execution.","triggerScenarios":"Executing a DMN decision through the engine (e.g. DmnEngine.executeDecide or an ExecuteDecisionActivityBehavior flow) where the internally constructed ExecuteDecisionContext is null — typically after a failed or misconfigured decision execution setup.","commonSituations":"Custom code building PersistHistoricDecisionExecutionCmd manually with a null context; engine bugs or subclass overrides that leave the context unset when history is enabled.","solutions":["Never construct PersistHistoricDecisionExecutionCmd manually; let the ExecuteDecisionActivityBehavior supply a properly built context","If writing custom behavior, build an ExecuteDecisionContext with non-null decisionExecution data before persisting history","Check for overrides or forks of ExecuteDecisionActivityBehavior that skip context creation"],"exampleFix":"// before\nnew PersistHistoricDecisionExecutionCmd(null).execute(commandContext);\n// after\nExecuteDecisionContext ctx = new ExecuteDecisionContext(decisionExecution);\nnew PersistHistoricDecisionExecutionCmd(ctx).execute(commandContext);","handlingStrategy":"validation","validationCode":"if (ctx == null || ctx.getDecisionExecution() == null) {\n    throw new IllegalStateException(\"ExecuteDecisionContext must be built before persisting history\");\n}","typeGuard":"boolean hasContext(ExecuteDecisionContext c) { return c != null && c.getDecisionExecution() != null; }","tryCatchPattern":"try {\n    behavior.execute(execution);\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"ExecuteDecisionContext is null\")) {\n        log.error(\"Decision context missing during history persist\", e);\n    }\n    throw e;\n}","preventionTips":["Do not construct engine-internal commands directly; rely on ExecuteDecisionActivityBehavior","When subclassing decision behavior, always build the context before invoking the persist command","Enable history only after verifying the decision pipeline sets up its context"],"tags":["java","flowable-dmn","null-check","history"],"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"}