flowable/flowable-engine · error · FlowableException
DMN decision with key ${finalDecisionKeyValue} did not hit a
Error message
DMN decision with key ${finalDecisionKeyValue} did not hit any rules for the provided input. In ${execution} What it means
The decision executed successfully but no rule matched the provided input, and the task's 'decisionTableThrowErrorOnNoHit' flag field (EXPRESSION_DECISION_TABLE_THROW_ERROR_FLAG) was set so that this condition must fail the task. Flowable throws this FlowableException when the flag is the literal 'true'; if the flag is an expression, it throws only when that expression evaluates to Boolean true. It signals incomplete decision coverage rather than an engine malfunction.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/DmnActivityBehavior.java:130
if (decisionExecutionAuditContainer.isFailed()) {
throw new FlowableException("DMN decision with key " + finalDecisionKeyValue + " execution failed in " + execution,
decisionExecutionAuditContainer.getException());
}
/*Throw error if there were no rules hit when the flag indicates to do this.*/
FieldExtension throwErrorFieldExtension = DelegateHelper.getFlowElementField(execution, EXPRESSION_DECISION_TABLE_THROW_ERROR_FLAG);
if (throwErrorFieldExtension != null) {
String throwErrorString = null;
if (StringUtils.isNotEmpty(throwErrorFieldExtension.getStringValue())) {
throwErrorString = throwErrorFieldExtension.getStringValue();
} else if (StringUtils.isNotEmpty(throwErrorFieldExtension.getExpression())) {
throwErrorString = throwErrorFieldExtension.getExpression();
}
if (decisionExecutionAuditContainer.getDecisionResult().isEmpty() && throwErrorString != null) {
if ("true".equalsIgnoreCase(throwErrorString)) {
throw new FlowableException("DMN decision with key " + finalDecisionKeyValue + " did not hit any rules for the provided input. In " + execution);
} else if (!"false".equalsIgnoreCase(throwErrorString)) {
Expression expression = expressionManager.createExpression(throwErrorString);
Object expressionValue = expression.getValue(execution);
if (expressionValue instanceof Boolean && ((Boolean) expressionValue)) {
throw new FlowableException("DMN decision with key " + finalDecisionKeyValue + " did not hit any rules for the provided input. In " + execution);
}
}
}
}
if (processEngineConfiguration.getDecisionTableVariableManager() != null) {
if (decisionExecutionAuditContainer instanceof DecisionServiceExecutionAuditContainer decisionServiceExecutionAuditContainer) {
processEngineConfiguration.getDecisionTableVariableManager().setDecisionServiceVariablesOnExecution(decisionServiceExecutionAuditContainer.getDecisionServiceResult(),
finalDecisionKeyValue, execution, processEngineConfiguration.getObjectMapper(), decisionExecutionAuditContainer.isMultipleResults());
} else {
processEngineConfiguration.getDecisionTableVariableManager().setVariablesOnExecution(decisionExecutionAuditContainer.getDecisionResult(),
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Add a catch-all/default rule to the decision table covering unmatched inputs
- Set the throw-error field to "false" (or remove it) if no-hit should be tolerated and handled by checking the empty result instead
- Fix or validate the input variables before the DMN task so they fall inside existing rule conditions
- Keep the flag but wrap the DMN task in a boundary error event in the process model to handle no-hit outcomes gracefully
Example fix
// before (BPMN XML) <flowable:field name="decisionTableThrowErrorOnNoHit" stringValue="true" /> // after <flowable:field name="decisionTableThrowErrorOnNoHit" stringValue="false" /> // or add a default rule to the DMN table
Defensive patterns
Strategy: validation
Validate before calling
DecisionExecutionAuditContainer audit = executeDecisionBuilder.executeWithAuditTrail();
if (audit.getDecisionResult() == null || audit.getDecisionResult().isEmpty()) {
log.warn("No DMN rule hit for inputs {}", inputVars);
} Try / catch
try {
taskService.complete(taskId);
} catch (FlowableException e) {
if (e.getMessage().contains("did not hit any rules")) {
// handle no-hit business case explicitly
} else throw e;
} Prevention
- Add a default/fallback rule to every decision table
- Only enable the throw-no-hit flag when no-hit is a true business failure
- Test decision tables with boundary and out-of-range inputs
- Validate input data against rule conditions before the DMN task
When it happens
Trigger: decisionExecutionAuditContainer.getDecisionResult().isEmpty() (zero rules hit) AND the throwError field extension resolves to "true" or to an expression evaluating to true; typically input data doesn't satisfy any rule's conditions while strict no-hit enforcement is configured.
Common situations: Incomplete rule coverage in the decision table (no default/fallback rule); input values outside the ranges covered by rules; caller passes unexpected/edge-case data (null age, unknown category); deliberate strict mode where any no-hit must fail the process.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- DMN repository service is not available
- Dmn engine is not configured
- more than one result in decision:
- more than one result
- HitPolicy behavior: %s not configured
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/c454dbf754fb4aa6.
Report an issue: GitHub.