flowable/flowable-engine · error · FlowableObjectNotFoundException
No channel definition found for key '' for tenant identifier
Error message
No channel definition found for key '' for tenant identifier
What it means
Thrown when resolving a channel definition by key for a specific tenantId and no deployed definition exists for that key+tenant combination. FlowableObjectNotFoundException including the tenant identifier.
Source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/cmd/GetChannelModelCmd.java:94
throw new FlowableObjectNotFoundException("No channel definition found for key '" + channelDefinitionKey + "'", ChannelDefinitionEntity.class);
}
} else if (channelDefinitionKey != null && tenantId != null && !EventRegistryEngineConfiguration.NO_TENANT_ID.equals(tenantId) &&
(parentDeploymentId == null || eventEngineConfiguration.isAlwaysLookupLatestDefinitionVersion())) {
channelDefinitionEntity = channelDefinitionEntityManager.findLatestChannelDefinitionByKeyAndTenantId(channelDefinitionKey, tenantId);
if (channelDefinitionEntity == null && eventEngineConfiguration.isFallbackToDefaultTenant()) {
String defaultTenant = eventEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.EVENT_REGISTRY, channelDefinitionKey);
if (StringUtils.isNotEmpty(defaultTenant)) {
channelDefinitionEntity = channelDefinitionEntityManager.findLatestChannelDefinitionByKeyAndTenantId(channelDefinitionKey, defaultTenant);
} else {
channelDefinitionEntity = channelDefinitionEntityManager.findLatestChannelDefinitionByKey(channelDefinitionKey);
}
}
if (channelDefinitionEntity == null) {
throw new FlowableObjectNotFoundException("No channel definition found for key '" + channelDefinitionKey + "' for tenant identifier " + tenantId, ChannelDefinitionEntity.class);
}
} else if (channelDefinitionKey != null && (tenantId == null || EventRegistryEngineConfiguration.NO_TENANT_ID.equals(tenantId)) && parentDeploymentId != null) {
List<EventDeployment> eventDeployments = deploymentManager.getDeploymentEntityManager().findDeploymentsByQueryCriteria(
new EventDeploymentQueryImpl().parentDeploymentId(parentDeploymentId));
if (eventDeployments != null && eventDeployments.size() > 0) {
channelDefinitionEntity = channelDefinitionEntityManager.findChannelDefinitionByDeploymentAndKey(eventDeployments.get(0).getId(), channelDefinitionKey);
}
if (channelDefinitionEntity == null) {
channelDefinitionEntity = channelDefinitionEntityManager.findLatestChannelDefinitionByKey(channelDefinitionKey);
}
if (channelDefinitionEntity == null) {
throw new FlowableObjectNotFoundException("No channel definition found for key '" + channelDefinitionKey +
"' for parent deployment id " + parentDeploymentId, ChannelDefinitionEntity.class);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Deploy the channel definition with the same tenantId passed at lookup time (DeploymentBuilder.tenantId(...))
- Verify the exact tenant id string in the database matches the lookup value
- If the channel is tenant-agnostic, look up without a tenant or use the engine's NO_TENANT_ID value
Example fix
// before
repositoryService.createDeployment().addClasspathResource("sms-channel.xml").deploy(); // no tenant
getChannelModel("sms-channel", null, "acme"); // looks up tenant 'acme' -> not found
// after
repositoryService.createDeployment().addClasspathResource("sms-channel.xml").tenantId("acme").deploy();
getChannelModel("sms-channel", null, "acme"); Defensive patterns
Strategy: validation
Validate before calling
ChannelDefinition cd = repositoryService.createChannelDefinitionQuery()
.channelDefinitionKey(key).latest().singleResult(); // tenant-filtered variant if available
if (cd == null) throw new IllegalStateException("channel " + key + " not deployed for tenant " + tenantId); Try / catch
try {
return repositoryService.getChannelModel(null, key, tenantId, null);
} catch (FlowableObjectNotFoundException e) {
LOGGER.error("channel {} missing for tenant {}", key, tenantId);
throw e;
} Prevention
- Always set tenantId on the DeploymentBuilder when the runtime uses tenant-scoped lookups
- Use one constant/property source for tenant ids across deploy and lookup code
- Provision tenant data as part of tenant onboarding
When it happens
Trigger: getChannelModel with channelDefinitionKey plus a non-null tenantId (not NO_TENANT_ID) where findLatestChannelDefinitionByKeyAndTenantId returns nothing — the channel was deployed without that tenant id or without tenant isolation.
Common situations: Deploying channel definitions without setting the tenant id in the deployment while the runtime lookup passes a tenant; tenant name mismatch (case/prefix); multi-tenant data not provisioned for a new 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
- No process definition found for key '${processDefinitionKey}
- No channel definition found for key '' for parent deployment
- No decision found for key <decisionKey>. There was also no f
- No decision found for key <decisionKey>. There was also no f
- Could not find deployment with id <deploymentId>
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d0a44b9985b367d5.
Report an issue: GitHub.