flowable/flowable-engine · error · FlowableException

Could not execute decision: no externalRef defined for ${pla

Error message

Could not execute decision: no externalRef defined for ${planItemInstanceEntity}

What it means

When a decision task references its decision via an external reference, the behavior evaluates the decision ref expression and requires a non-empty externalRef string. If the expression is defined but evaluates to null/empty, the engine cannot identify which DMN decision to execute and throws this FlowableException.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/DecisionTaskActivityBehavior.java:79

        DmnDecisionService dmnRuleService = CommandContextUtil.getDmnRuleService(commandContext);
        if (dmnRuleService == null) {
            throw new FlowableException("Could not execute decision instance: no dmn service found. For " + planItemInstanceEntity);
        }

        String externalRef = null;
        if (decisionTask != null && decisionTask.getDecision() != null &&
                StringUtils.isNotEmpty(decisionTask.getDecision().getExternalRef())) {
            
            externalRef = decisionTask.getDecision().getExternalRef();
            
        } else if (decisionRefExpression != null) {
            Object externalRefValue = decisionRefExpression.getValue(planItemInstanceEntity);
            if (externalRefValue != null) {
                externalRef = externalRefValue.toString();
            }
            
            if (StringUtils.isEmpty(externalRef)) {
                throw new FlowableException("Could not execute decision: no externalRef defined for " + planItemInstanceEntity);
            }
        }

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);

        ExecuteDecisionBuilder executeDecisionBuilder = dmnRuleService.createExecuteDecisionBuilder().
            decisionKey(externalRef).
            instanceId(planItemInstanceEntity.getCaseInstanceId()).
            executionId(planItemInstanceEntity.getId()).
            activityId(decisionTask.getId()).
            scopeType(ScopeTypes.CMMN).
            variables(planItemInstanceEntity.getVariables()).
            tenantId(planItemInstanceEntity.getTenantId());

        String fallBackToDefaultTenantValue = getFieldString(STRING_DECISION_TABLE_FALLBACK_TO_DEFAULT_TENANT);
        if (Boolean.parseBoolean(fallBackToDefaultTenantValue)) {
            executeDecisionBuilder.fallbackToDefaultTenant();
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set the variable(s) referenced by the decision ref expression before the plan item reaches ACTIVE state (e.g. via case start form, data object, or a preceding service task).
  2. Fix the expression syntax in the case model so it resolves to the decision key, e.g. ${decisionKey} where decisionKey is a case variable.
  3. Set a literal externalRef on the decision task element in the CMMN XML if the key is static.
  4. Guard the flow: use a condition/sentry so the decision task only activates once the referenced variable is populated.

Example fix

// before: activates with missing variable
caseRuntimeService.setVariable(caseInstanceId, "decisonKey", "myDecision"); // typo -> expression yields null
// after
caseRuntimeService.setVariable(caseInstanceId, "decisionKey", "myDecision");
Defensive patterns

Strategy: validation

Validate before calling

String externalRef = (String) caseInstance.getCaseVariables().get("decisionKey");
if (externalRef == null || externalRef.isBlank()) {
    throw new IllegalArgumentException("decisionKey variable must be set before decision task activates");
}

Type guard

Object v = planItemInstance.getCaseVariables().get("decisionKey");
if (v instanceof String s && !s.isEmpty()) { /* safe to proceed */ }

Try / catch

try {
    caseRuntimeService.completePlanItemInstance(planItemId);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Could not execute decision: no externalRef")) {
        log.error("Decision ref variable missing on case {}", caseInstanceId);
    }
    throw e;
}

Prevention

When it happens

Trigger: A decision task with an externalRef (decision ref) expression whose evaluation on the plan item instance yields null or the empty string at plan item activation.

Common situations: Case variables not set before the decision task activates; a typo in the expression variable name; the decision's externalRef attribute left empty in the case model while the expression path was expected to supply it.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/431af28f70526bc1. Report an issue: GitHub.