flowable/flowable-engine · error · FlowableObjectNotFoundException
No decision found for key <decisionKey>, parent deployment i
Error message
No decision found for key <decisionKey>, parent deployment id <parentDeploymentId> and tenant id: <tenantId>. There was also no fall back decision found without parent deployment id.
What it means
Flowable DMN throws this FlowableObjectNotFoundException when resolving a decision by key, parent deployment id and tenant id finds no matching Decision row in the DMN repository, and a fallback lookup without the parent deployment id also fails. The engine cannot locate any deployed decision for the given key/tenant combination, so decision execution is aborted before planning.
Source
Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/cmd/AbstractExecuteDecisionCmd.java:112
if (executeDecisionContext.isFallbackToDefaultTenant() || dmnEngineConfiguration.isFallbackToDefaultTenant()) {
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 table found without tenant.");
}
}
} else {
throw new FlowableObjectNotFoundException("No decision found for key: " + decisionKey +
", parent deployment id " + parentDeploymentId + " and tenant id: " + tenantId +
". There was also no fall back decision found without parent deployment id.");
}
}
}
} else if (StringUtils.isNotEmpty(decisionKey) && StringUtils.isNotEmpty(parentDeploymentId) &&
!dmnEngineConfiguration.isAlwaysLookupLatestDefinitionVersion()) {
List<DmnDeployment> dmnDeployments = CommandContextUtil.getDeploymentEntityManager().findDeploymentsByQueryCriteria(
new DmnDeploymentQueryImpl().parentDeploymentId(parentDeploymentId));
if (dmnDeployments != null && dmnDeployments.size() != 0) {
decision = decisionEntityManager.findDecisionByDeploymentAndKey(dmnDeployments.get(0).getId(), decisionKey);
}
if (decision == null) {
// If there is no decision table found linked to the deployment id, try to find one without a specific deployment id.View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify with a repository query that a Decision row exists for the given key and tenantId (ACT_DMN_DECISION / DmnRepositoryService.createDecisionQuery().decisionKey(...).tenantId(...)).
- Remove or correct parentDeploymentId so the lookup falls back to latest-by-key-and-tenant, or pass the correct parent deployment id the decision was deployed with.
- Correct the tenantId (or deploy the decision under the expected tenant) so the tenant-scoped query matches.
- Enable fallbackToDefaultTenant in DmnEngineConfiguration if the decision should be resolved from the default tenant.
- Redeploy the DMN resource (.dmn.xml) to the target tenant/deployment.
Example fix
// before
dmnEngine.executeDecision(new ExecuteDecisionBuilderImpl().decisionKey("myDecision").parentDeploymentId("dep-123").tenantId("wrong-tenant"));
// after
DmnRepositoryService repo = dmnEngine.getDmnRepositoryService();
if (repo.createDecisionQuery().decisionKey("myDecision").tenantId("acme").count() == 0) {
repo.createDeployment().addClasspathResource("diagrams/myDecision.dmn").tenantId("acme").deploy();
}
dmnEngine.executeDecision(new ExecuteDecisionBuilderImpl().decisionKey("myDecision").tenantId("acme")); Defensive patterns
Strategy: validation
Validate before calling
long count = dmnRepositoryService.createDecisionQuery().decisionKey(key).parentDeploymentId(parentDepId).tenantId(tenantId).count();
if (count == 0 && dmnRepositoryService.createDecisionQuery().decisionKey(key).tenantId(tenantId).count() == 0) {
throw new IllegalStateException("Decision " + key + " not deployed for tenant " + tenantId);
} Try / catch
try { dmnEngine.executeDecision(builder.decisionKey(key).parentDeploymentId(dep).tenantId(tenant)); }
catch (FlowableObjectNotFoundException e) { log.error("Decision {} missing for tenant {}", key, tenant, e); deployDecision(key, tenant); } Prevention
- Deploy DMN resources per tenant as part of environment setup
- Validate key/tenant existence with a DecisionQuery before execution
- Keep parentDeploymentId usage minimal; prefer key+tenant resolution
- Enable fallbackToDefaultTenant where cross-tenant resolution is acceptable
When it happens
Trigger: Calling the DMN engine (e.g. ExecuteDecisionCmd via DmnEngineService or a rule task) with decisionKey set, a non-empty parentDeploymentId and tenantId, where neither findDecisionByKeyParentDeploymentIdAndTenantId nor the fallback findLatestDecisionByKeyAndTenantId returns a row.
Common situations: Decision not deployed to the tenant's deployments; tenant id typo; decision deployed only under a different parent deployment (e.g. process app) id; cascade deployment removed the decision; fallback-to-default-tenant disabled while the decision lives under the default tenant.
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
- Could not find deployment with id <deploymentId>
- DMN decision with key ${externalRef} was not executed. For $
- Required decision <decisionId> is not available
- No decision found for key <decisionKey>. There was also no f
- No decision found for key <decisionKey>. There was also no f
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e3b5aee2e865083c.
Report an issue: GitHub.