flowable/flowable-engine · error · FlowableException
The channel xml key detection value was not found for the…
Error message
The channel xml key detection value was not found for the channel model with key ${channelModel.key}. One of fixedValue, xmlPathExpression, delegateExpression should be set. What it means
Thrown when an XML inbound channel has a ChannelEventKeyDetection but none of fixedValue, xmlXPathExpression, or delegateExpression is populated. The block exists yet defines no key detection mechanism, so no InboundEventKeyDetector<Document> can be created.
Solutions
- Populate one of keyDetection.fixedValue, keyDetection.xmlXPathExpression, or keyDetection.delegateExpression.
- Use setXmlXPathExpression with an XPath that selects the event key from the document.
- Use setDelegateExpression for a custom InboundEventKeyDetector<Document> bean.
- If the detection was meant for JSON, move the channel to the JSON pipeline or convert the detection to an XPath expression.
Example fix
// before
ChannelEventKeyDetection keyDetection = new ChannelEventKeyDetection();
keyDetection.setJsonField("type"); // ignored on XML channels
// after
ChannelEventKeyDetection keyDetection = new ChannelEventKeyDetection();
keyDetection.setXmlXPathExpression("/event/@type"); Defensive patterns
Strategy: validation
Validate before calling
ChannelEventKeyDetection kd = channelModel.getChannelEventKeyDetection();
if (kd != null && isBlank(kd.getFixedValue()) && isBlank(kd.getXmlXPathExpression())
&& isBlank(kd.getDelegateExpression())) {
throw new IllegalArgumentException("Empty keyDetection on XML channel " + channelModel.getKey());
} Type guard
null
Try / catch
try {
eventRegistry.registerChannelModel(channelModel);
} catch (FlowableException e) {
if (e.getMessage().contains("xml key detection value was not found")) {
logger.error("Set fixedValue/xmlXPathExpression/delegateExpression on channel {}", channelModel.getKey());
}
throw e;
} Prevention
- Use XML-specific options (xmlXPathExpression), not JSON ones (jsonField/jsonPointer)
- Test XPath expressions against sample XML documents before registering
- Keep one key detection option set per channel and delete leftover empty blocks
When it happens
Trigger: Registering an XML inbound channel with a non-null keyDetection where getFixedValue, getXmlXPathExpression and getDelegateExpression are all empty.
Common situations: Empty <keyDetection/> element in the channel model XML; using jsonField/jsonPointer (JSON-only options) on an XML channel — they are ignored here; attribute name typos during hand-editing.
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
- A channel key detection value is required for inbound…
- The channel deserializer expression for the channel model…
- The channel json key detection value was not found for the…
- The channel json tenant detection value was not found for…
- The channel payload extractor expression for the channel…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b18aa23511299cdd.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java:232
eventTransformer = resolveExpression(channelModel.getEventTransformerDelegateExpression(), InboundEventTransformer.class);
}
InboundEventKeyDetector<Document> eventKeyDetector;
ChannelEventKeyDetection keyDetection = channelModel.getChannelEventKeyDetection();
if (keyDetection == null) {
throw new FlowableException("A channel key detection value is required for inbound channel " + channelModel.getKey());
}
if (StringUtils.isNotEmpty(keyDetection.getFixedValue())) {
eventKeyDetector = new InboundEventStaticKeyDetector<>(keyDetection.getFixedValue());
} else if (StringUtils.isNotEmpty(keyDetection.getXmlXPathExpression())) {
eventKeyDetector = new XpathBasedInboundEventKeyDetector(keyDetection.getXmlXPathExpression());
} else if (StringUtils.isNotEmpty(keyDetection.getDelegateExpression())) {
//noinspection unchecked
eventKeyDetector = resolveExpression(keyDetection.getDelegateExpression(), InboundEventKeyDetector.class);
} 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()View on GitHub (pinned to d6d39ce1c6)