flowable/flowable-engine · error · FlowableObjectNotFoundException

No decision found for key

Error message

No decision found for key: <decisionKey> and tenantId: <tenantId>.

What it means

Thrown when a decision is resolved by key and tenantId with fallback-to-default-tenant disabled and no Decision exists for that exact key+tenantId combination. The engine refuses to fall back, so the lookup fails outright.

Solutions

  1. Enable fallbackToDefaultTenant in DmnEngineConfiguration (dmnEngineConfiguration.setFallbackToDefaultTenant(true)) or pass fallbackToDefaultTenant() on the builder so the default tenant can be used.
  2. Correct the tenantId to the tenant under which the .dmn file was deployed.
  3. Deploy the decision under the requested tenantId.
  4. Verify existence with DmnRepositoryService.createDecisionQuery().decisionKey(key).tenantId(tenantId).count().

Example fix

// before
dmnEngine.executeDecision(new ExecuteDecisionBuilderImpl().decisionKey("risk").tenantId("acme"));
// after
dmnEngine.executeDecision(new ExecuteDecisionBuilderImpl().decisionKey("risk").tenantId("acme").fallbackToDefaultTenant());
Defensive patterns

Strategy: fallback

Validate before calling

boolean exists = dmnRepositoryService.createDecisionQuery().decisionKey(key).tenantId(tenantId).count() > 0;
boolean fallback = dmnEngine.getDmnEngineConfiguration().isFallbackToDefaultTenant();
if (!exists && !fallback) throw new IllegalStateException("Decision " + key + " not in tenant " + tenantId + " and fallback disabled");

Try / catch

try { dmnEngine.executeDecision(builder.decisionKey(key).tenantId(tenantId)); }
catch (FlowableObjectNotFoundException e) { dmnEngine.executeDecision(builder.decisionKey(key).tenantId(defaultTenant)); }

Prevention

When it happens

Trigger: Executing a decision with decisionKey and tenantId set where isFallbackToDefaultTenant() is false (context and engine config) and findDecisionByKeyAndTenantId returns null.

Common situations: Decision deployed under a different tenant; tenantId spelled incorrectly; decision only in the default tenant while the caller passes an explicit tenant with fallback disabled; multi-tenant deployment mismatch after environment migration.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/0c7df93fc1da476c. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/cmd/AbstractExecuteDecisionCmd.java:162

                    String defaultTenant = dmnEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.DMN, decisionKey);
                    if (StringUtils.isNotEmpty(defaultTenant)) {
                        decision = decisionEntityManager.findLatestDecisionByKeyAndTenantId(decisionKey, defaultTenant);
                        if (decision == null) {
                            throw new FlowableObjectNotFoundException("No decision found for key: " + decisionKey +
                                ". There was also no fall back decision found for default tenant " +
                                defaultTenant + ".");
                        }

                    } else {
                        decision = decisionEntityManager.findLatestDecisionByKey(decisionKey);
                        if (decision == null) {
                            throw new FlowableObjectNotFoundException("No decision found for key: " + decisionKey +
                                ". There was also no fall back decision found without tenant.");
                        }
                    }

                } else {
                    throw new FlowableObjectNotFoundException(
                        "No decision found for key: " + decisionKey + " and tenantId: " + tenantId + ".");
                }
            }

        } else if (StringUtils.isNotEmpty(decisionKey)) {
            decision = decisionEntityManager.findLatestDecisionByKey(decisionKey);
            if (decision == null) {
                throw new FlowableObjectNotFoundException("No decision found for key: " + decisionKey + ".");
            }
            
        } else {
            throw new FlowableIllegalArgumentException("decisionKey is null");
        }

        executeDecisionContext.setDecisionId(decision.getId());
        executeDecisionContext.setDecisionVersion(decision.getVersion());
        executeDecisionContext.setDeploymentId(decision.getDeploymentId());

View on GitHub (pinned to d6d39ce1c6)