{"record":{"id":"5798711e534d1dad","repo":"flowable/flowable-engine","slug":"decisiontablereferencekey-is-a-required-field-exte","errorCode":null,"errorMessage":"decisionTableReferenceKey is a required field extension for the dmn task ${task.getId()} in ${execution}","messagePattern":"decisionTableReferenceKey is a required field extension for the dmn task (.+?) in (.+?)","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/DmnActivityBehavior.java","lineNumber":64,"sourceCode":"\r\n    protected static final String EXPRESSION_DECISION_TABLE_REFERENCE_KEY = \"decisionTableReferenceKey\";\r\n    protected static final String EXPRESSION_DECISION_TABLE_THROW_ERROR_FLAG = \"decisionTaskThrowErrorOnNoHits\";\r\n    protected static final String EXPRESSION_DECISION_TABLE_FALLBACK_TO_DEFAULT_TENANT = \"fallbackToDefaultTenant\";\r\n    protected static final String EXPRESSION_DECISION_TABLE_SAME_DEPLOYMENT = \"sameDeployment\";\r\n\r\n    protected Task task;\r\n\r\n    public DmnActivityBehavior(Task task) {\r\n        this.task = task;\r\n    }\r\n\r\n    @Override\r\n    public void execute(DelegateExecution execution) {\r\n        FieldExtension fieldExtension = DelegateHelper.getFlowElementField(execution, EXPRESSION_DECISION_TABLE_REFERENCE_KEY);\r\n        if (fieldExtension == null || ((fieldExtension.getStringValue() == null || fieldExtension.getStringValue().length() == 0) &&\r\n                (fieldExtension.getExpression() == null || fieldExtension.getExpression().length() == 0))) {\r\n\r\n            throw new FlowableException(\"decisionTableReferenceKey is a required field extension for the dmn task \" + task.getId() + \" in \" + execution);\r\n        }\r\n\r\n        String activeDecisionKey = null;\r\n        if (fieldExtension.getExpression() != null && fieldExtension.getExpression().length() > 0) {\r\n            activeDecisionKey = fieldExtension.getExpression();\r\n\r\n        } else {\r\n            activeDecisionKey = fieldExtension.getStringValue();\r\n        }\r\n\r\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();\r\n        ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();\r\n\r\n        if (processEngineConfiguration.isEnableProcessDefinitionInfoCache()) {\r\n            ObjectNode taskElementProperties = BpmnOverrideContext.getBpmnOverrideElementProperties(task.getId(), execution.getProcessDefinitionId());\r\n            activeDecisionKey = DynamicPropertyUtil.getActiveValue(activeDecisionKey, DynamicBpmnConstants.DMN_TASK_DECISION_TABLE_KEY, taskElementProperties);\r\n        }\r\n\r","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/DmnActivityBehavior.java#L46-L82","documentation":"A DMN (decision) task in a BPMN process must declare which decision table to execute via the 'decisionTableReferenceKey' field extension on the task element. When the DmnActivityBehavior executes and cannot find that field extension, or it has neither a string value nor an expression, it aborts the execution with this FlowableException. It is a model/configuration validation error, not a runtime failure of the decision itself.","triggerScenarios":"A <serviceTask flowable:delegateExpression=.../> or DMN task element is deployed without a <flowable:field name=\"decisionTableReferenceKey\"> child that has either a stringValue or an expression; the field name is misspelled so DelegateHelper.getFlowElementField returns null; or the field is present but empty.","commonSituations":"Hand-editing or generating BPMN XML without the field extension; renaming the field element while migrating from Activiti-style 'decisionTableReferenceKey' config; copying a task template that omitted the field; deploying a model exported by a tool that doesn't serialize Flowable field extensions.","solutions":["Add a field extension to the DMN task in the BPMN XML: <extensionElements><flowable:field name=\"decisionTableReferenceKey\" stringValue=\"myDecisionKey\"/></extensionElements>","If the key is dynamic, set the field's expression attribute instead of stringValue, e.g. expression=\"${decisionKeyVar}\"","Verify the field name is exactly 'decisionTableReferenceKey' (case-sensitive) on the task element","Redeploy/restart the process definition after fixing the XML so the new model is used"],"exampleFix":"// before (BPMN XML)\n<serviceTask id=\"dmnTask\" flowable:type=\"dmn\" />\n// after\n<serviceTask id=\"dmnTask\" flowable:type=\"dmn\">\n  <extensionElements>\n    <flowable:field name=\"decisionTableReferenceKey\" stringValue=\"myDecisionTable\" />\n  </extensionElements>\n</serviceTask>","handlingStrategy":"validation","validationCode":"ServiceTask task = (ServiceTask) bpmnModel.getFlowElement(processId, \"dmnTask\");\nFieldExtension ext = (FieldExtension) task.getFields().stream()\n    .filter(f -> \"decisionTableReferenceKey\".equals(f.getFieldName()))\n    .findFirst().orElse(null);\nboolean valid = ext != null &&\n    ((ext.getStringValue() != null && !ext.getStringValue().isEmpty()) ||\n     (ext.getExpression() != null && !ext.getExpression().isEmpty()));\nif (!valid) throw new IllegalStateException(\"DMN task missing decisionTableReferenceKey field\");","typeGuard":"boolean hasDecisionKeyField(FlowElement el) {\n  if (!(el instanceof ServiceTask)) return false;\n  return ((ServiceTask) el).getFields().stream()\n    .anyMatch(f -> \"decisionTableReferenceKey\".equals(f.getFieldName())\n      && ((f.getStringValue() != null && !f.getStringValue().isEmpty())\n        || (f.getExpression() != null && !f.getExpression().isEmpty())));\n}","tryCatchPattern":null,"preventionTips":["Always define decisionTableReferenceKey on every DMN task element","Validate BPMN models at deploy time with automated checks for required field extensions","Use a modeler template/profile that pre-populates the required field"],"tags":["flowable","bpmn","dmn","configuration","missing-field-extension"],"backgroundTag":"missing-required-config-field","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"}