flowable/flowable-engine · error · FlowableException
The channel xml tenant detection value was not found for…
Error message
The channel xml tenant detection value was not found for the channel model with key ${channelModel.key}. One of fixedValue, xmlPathExpression (or xPathExpression), delegateExpression should be set. What it means
Thrown when an XML inbound channel declares a ChannelEventTenantIdDetection but none of fixedValue, xmlPathExpression (or the legacy xPathExpression property), or delegateExpression is set. An empty tenant-detection block cannot produce an InboundEventTenantDetector.
Solutions
- Set one of tenantDetection.fixedValue, tenantDetection.xmlPathExpression (or legacy xPathExpression), or tenantDetection.delegateExpression.
- If multi-tenancy is not used, remove the tenant detection block instead of leaving it empty.
- Use an XPath such as setXmlXPathExpression("/event/@tenant") to extract the tenant from the document.
- Check the ChannelEventTenantIdDetection getter/setter naming (xPath vs xmlPath) used by your Flowable version and set the matching property.
Example fix
// before
ChannelEventTenantIdDetection t = new ChannelEventTenantIdDetection();
t.setJsonPointerExpression("/tenant"); // not read by the XML pipeline
// after
ChannelEventTenantIdDetection t = new ChannelEventTenantIdDetection();
t.setXmlXPathExpression("/event/@tenant"); Defensive patterns
Strategy: validation
Validate before calling
ChannelEventTenantIdDetection td = channelModel.getChannelEventTenantIdDetection();
if (td != null && isBlank(td.getFixedValue()) && isBlank(td.getXmlXPathExpression())
&& isBlank(td.getxPathExpression()) && isBlank(td.getDelegateExpression())) {
throw new IllegalArgumentException("Empty tenantIdDetection on XML channel " + channelModel.getKey());
} Type guard
null
Try / catch
try {
eventRegistry.registerChannelModel(channelModel);
} catch (FlowableException e) {
if (e.getMessage().contains("xml tenant detection value was not found")) {
logger.error("Set fixedValue/xmlPathExpression/xPathExpression/delegateExpression on channel {}", channelModel.getKey());
}
throw e;
} Prevention
- Check your Flowable version's property naming (xPathExpression legacy vs xmlPathExpression) and set the right one
- Remove tenant detection blocks when multi-tenancy is unused
- Validate tenant XPath expressions with sample documents
When it happens
Trigger: Registering an XML inbound channel with a non-null channelEventTenantIdDetection where getFixedValue, getXmlXPathExpression/getxPathExpression and getDelegateExpression are all empty.
Common situations: Property-name confusion between xPathExpression (legacy) and xmlPathExpression — setting the wrong one leaves both empty; empty <tenantIdDetection/> element; copying a JSON tenant detection (jsonPointer) into an XML channel where it is not read.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- The channel json tenant detection value was not found for…
- A channel key detection value is required for inbound…
- Could not deserialize event to xml
- Could not evaluate xpath expression
- Could not evaluate xpath expression
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/62dfd86e7be20948.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java:249
} else {
throw new FlowableException(
"The channel xml key detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, xmlPathExpression, delegateExpression should be set.");
}
ChannelEventTenantIdDetection channelEventTenantIdDetection = channelModel.getChannelEventTenantIdDetection();
if (channelEventTenantIdDetection != null) {
if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getFixedValue())) {
eventTenantDetector = new InboundEventStaticTenantDetector<>(channelEventTenantIdDetection.getFixedValue());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getXmlXPathExpression())) {
eventTenantDetector = new XpathBasedInboundEventTenantDetector(channelEventTenantIdDetection.getXmlXPathExpression());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getxPathExpression())) {
eventTenantDetector = new XpathBasedInboundEventTenantDetector(channelEventTenantIdDetection.getxPathExpression());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getDelegateExpression())) {
//noinspection unchecked
eventTenantDetector = resolveExpression(channelEventTenantIdDetection.getDelegateExpression(), InboundEventTenantDetector.class);
} else {
throw new FlowableException(
"The channel xml tenant detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, xmlPathExpression (or xPathExpression), delegateExpression should be set.");
}
}
return new DefaultInboundEventProcessingPipeline<>(eventRepositoryService, eventDeserializer, eventFilter,
eventKeyDetector, eventTenantDetector, eventPayloadExtractor, eventTransformer, engineConfiguration);
}
protected <T> InboundEventPayloadExtractor<T> createInboundEventPayloadExtractor(InboundChannelModel channelModel,
InboundEventPayloadExtractor<T> payloadExtractorProvider) {
InboundEventPayloadExtractor<T> modelEventPayloadExtractor;
if (StringUtils.isEmpty(channelModel.getPayloadExtractorDelegateExpression())) {
modelEventPayloadExtractor = payloadExtractorProvider;
} else {
//noinspection unchecked
modelEventPayloadExtractor = resolveExpression(channelModel.getPayloadExtractorDelegateExpression(), InboundEventPayloadExtractor.class);View on GitHub (pinned to d6d39ce1c6)