flowable/flowable-engine · error · FlowableException
The channel expression tenant detection value was not found
Error message
The channel expression tenant detection value was not found for the channel model with key ${channelModel.key}. One of fixedValue, jsonField, jsonPointerExpression, xmlXPathExpression, delegateExpression should be set. What it means
Analogous to key detection, inbound channels may declare how the tenant id is extracted from an event via ChannelEventTenantIdDetection. If such a detection object is present but none of fixedValue, jsonField, jsonPointerExpression, xmlXPathExpression, or delegateExpression is populated, Flowable cannot build an InboundEventTenantDetector and throws this error in createExpressionEventProcessingPipeline.
Source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java:359
eventKeyDetector = new XpathBasedInboundEventKeyDetector(keyDetection.getXmlXPathExpression());
} else {
throw new FlowableException(
"The channel expression key detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, jsonField, jsonPointerExpression, xmlXPathExpression, delegateExpression should be set.");
}
ChannelEventTenantIdDetection channelEventTenantIdDetection = channelModel.getChannelEventTenantIdDetection();
if (channelEventTenantIdDetection != null) {
if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getDelegateExpression())) {
eventTenantDetector = resolveExpression(channelEventTenantIdDetection.getDelegateExpression(), InboundEventTenantDetector.class);
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getFixedValue())) {
eventTenantDetector = new InboundEventStaticTenantDetector<>(channelEventTenantIdDetection.getFixedValue());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getJsonPointerExpression())) {
eventTenantDetector = new JsonPointerBasedInboundEventTenantDetector(channelEventTenantIdDetection.getJsonPointerExpression());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getxPathExpression())) {
eventTenantDetector = new XpathBasedInboundEventTenantDetector(channelEventTenantIdDetection.getxPathExpression());
} else {
throw new FlowableException(
"The channel expression tenant detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, jsonField, jsonPointerExpression, xmlXPathExpression, delegateExpression should be set.");
}
}
//noinspection unchecked
return new DefaultInboundEventProcessingPipeline(eventRepositoryService, eventDeserializer, eventFilter,
eventKeyDetector, eventTenantDetector, eventPayloadExtractor, eventTransformer, engineConfiguration);
}
protected <T> T resolveExpression(String expression, Class<T> type) {
Object value = CommandContextUtil.getEventRegistryConfiguration().getExpressionManager()
.createExpression(expression)
.getValue(new VariableContainerWrapper(Collections.emptyMap()));
if (type.isInstance(value)) {
return type.cast(value);
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Populate one detection property on the ChannelEventTenantIdDetection, e.g. tenantIdDetectionFixedValue("tenant-1") or tenantIdDetectionJsonField("tenantId")
- Remove the tenant detection entirely if tenant awareness is not needed for this channel (null detection is allowed)
- If no static/expressed value fits, wire a custom InboundEventTenantDetector bean via delegateExpression
Example fix
// before
ChannelEventTenantIdDetection d = new ChannelEventTenantIdDetection();
channelModel.setChannelEventTenantIdDetection(d); // all fields empty
// after
ChannelEventTenantIdDetection d = new ChannelEventTenantIdDetection();
d.setFixedValue("acme");
channelModel.setChannelEventTenantIdDetection(d); Defensive patterns
Strategy: validation
Validate before calling
ChannelEventTenantIdDetection d = channelModel.getChannelEventTenantIdDetection();
if (d != null && (isEmpty(d.getFixedValue()) && isEmpty(d.getJsonField()) && isEmpty(d.getJsonPointerExpression()) && isEmpty(d.getxPathExpression()) && isEmpty(d.getDelegateExpression()))) {
throw new IllegalArgumentException("Channel '" + channelModel.getKey() + "' tenant detection has no value set");
} Prevention
- Either fully configure tenant detection or omit it entirely (null is valid)
- Use tenantIdDetectionFixedValue for single-tenant deployments
- Test multi-tenant channel registration in a staging environment before production
When it happens
Trigger: registerChannelModel on an inbound channel where channelModel.getChannelEventTenantIdDetection() is non-null but all its detection properties are empty, falling through the if/else-if chain to the throw.
Common situations: Adding a tenantIdDetection element to channel XML but leaving the attribute empty; builder call like keyDetectionTenantId() without arguments; copy-paste of channel config where the tenant detection values were removed.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- No event definition found for event key ${sendEventServiceTa
- No channel keys configured for ${execution}
- A channel key detection value is required for the channel mo
- form tenantId is null
- No event definition found for key '${eventDefinitionKey}' fo
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/55e83c7a108c8169.
Report an issue: GitHub.