flowable/flowable-engine · error · FlowableException
decisionTableReferenceKey is a required field extension for
Error message
decisionTableReferenceKey is a required field extension for the dmn task ${task.getId()} in ${execution} What it means
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.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/DmnActivityBehavior.java:64
protected static final String EXPRESSION_DECISION_TABLE_REFERENCE_KEY = "decisionTableReferenceKey";
protected static final String EXPRESSION_DECISION_TABLE_THROW_ERROR_FLAG = "decisionTaskThrowErrorOnNoHits";
protected static final String EXPRESSION_DECISION_TABLE_FALLBACK_TO_DEFAULT_TENANT = "fallbackToDefaultTenant";
protected static final String EXPRESSION_DECISION_TABLE_SAME_DEPLOYMENT = "sameDeployment";
protected Task task;
public DmnActivityBehavior(Task task) {
this.task = task;
}
@Override
public void execute(DelegateExecution execution) {
FieldExtension fieldExtension = DelegateHelper.getFlowElementField(execution, EXPRESSION_DECISION_TABLE_REFERENCE_KEY);
if (fieldExtension == null || ((fieldExtension.getStringValue() == null || fieldExtension.getStringValue().length() == 0) &&
(fieldExtension.getExpression() == null || fieldExtension.getExpression().length() == 0))) {
throw new FlowableException("decisionTableReferenceKey is a required field extension for the dmn task " + task.getId() + " in " + execution);
}
String activeDecisionKey = null;
if (fieldExtension.getExpression() != null && fieldExtension.getExpression().length() > 0) {
activeDecisionKey = fieldExtension.getExpression();
} else {
activeDecisionKey = fieldExtension.getStringValue();
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();
if (processEngineConfiguration.isEnableProcessDefinitionInfoCache()) {
ObjectNode taskElementProperties = BpmnOverrideContext.getBpmnOverrideElementProperties(task.getId(), execution.getProcessDefinitionId());
activeDecisionKey = DynamicPropertyUtil.getActiveValue(activeDecisionKey, DynamicBpmnConstants.DMN_TASK_DECISION_TABLE_KEY, taskElementProperties);
}
View on GitHub (pinned to d6d39ce1c6)
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
Example fix
// before (BPMN XML)
<serviceTask id="dmnTask" flowable:type="dmn" />
// after
<serviceTask id="dmnTask" flowable:type="dmn">
<extensionElements>
<flowable:field name="decisionTableReferenceKey" stringValue="myDecisionTable" />
</extensionElements>
</serviceTask> Defensive patterns
Strategy: validation
Validate before calling
ServiceTask task = (ServiceTask) bpmnModel.getFlowElement(processId, "dmnTask");
FieldExtension ext = (FieldExtension) task.getFields().stream()
.filter(f -> "decisionTableReferenceKey".equals(f.getFieldName()))
.findFirst().orElse(null);
boolean valid = ext != null &&
((ext.getStringValue() != null && !ext.getStringValue().isEmpty()) ||
(ext.getExpression() != null && !ext.getExpression().isEmpty()));
if (!valid) throw new IllegalStateException("DMN task missing decisionTableReferenceKey field"); Type guard
boolean hasDecisionKeyField(FlowElement el) {
if (!(el instanceof ServiceTask)) return false;
return ((ServiceTask) el).getFields().stream()
.anyMatch(f -> "decisionTableReferenceKey".equals(f.getFieldName())
&& ((f.getStringValue() != null && !f.getStringValue().isEmpty())
|| (f.getExpression() != null && !f.getExpression().isEmpty())));
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- DMN repository service is not available
- Dmn engine is not configured
- HitPolicy behavior: %s not configured
- DMN decision with key ${finalDecisionKeyValue} did not hit a
- Could not resolve key for: ${eventDefinitionKey} for ${execu
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5798711e534d1dad.
Report an issue: GitHub.