flowable/flowable-engine · error · FlowableException
The channel json key detection value was not found for the…
Error message
The channel json key detection value was not found for the channel model with key ${channelModel.key}. One of fixedValue, jsonField, jsonPointerExpression or delegateExpression should be set. What it means
Thrown when a JSON inbound channel HAS a ChannelEventKeyDetection, but none of the four supported sources (fixedValue, jsonField, jsonPointerExpression, delegateExpression) is populated. The key-detection block exists but is effectively empty, so no InboundEventKeyDetector can be built.
Solutions
- Populate exactly one of keyDetection.fixedValue, keyDetection.jsonField, keyDetection.jsonPointerExpression, or keyDetection.delegateExpression.
- For nested JSON keys prefer setJsonPointerExpression("/event/type").
- If reusing a custom detector, set setDelegateExpression("${myKeyDetector}") to an InboundEventKeyDetector<JsonNode> bean.
- Validate the channel model JSON against the Flowable channel schema to ensure attribute names match (e.g. 'jsonField' not 'field').
Example fix
// before
ChannelEventKeyDetection keyDetection = new ChannelEventKeyDetection(); // empty — no field set
channelModel.setChannelEventKeyDetection(keyDetection);
// after
ChannelEventKeyDetection keyDetection = new ChannelEventKeyDetection();
keyDetection.setJsonPointerExpression("/event/type");
channelModel.setChannelEventKeyDetection(keyDetection); Defensive patterns
Strategy: validation
Validate before calling
ChannelEventKeyDetection kd = channelModel.getChannelEventKeyDetection();
if (kd != null && isBlank(kd.getFixedValue()) && isBlank(kd.getJsonField())
&& isBlank(kd.getJsonPointerExpression()) && isBlank(kd.getDelegateExpression())) {
throw new IllegalArgumentException("Empty keyDetection on channel " + channelModel.getKey());
} Type guard
null
Try / catch
try {
eventRegistry.registerChannelModel(channelModel);
} catch (FlowableException e) {
if (e.getMessage().contains("json key detection value was not found")) {
logger.error("Set fixedValue/jsonField/jsonPointerExpression/delegateExpression on channel {}", channelModel.getKey());
}
throw e;
} Prevention
- Set exactly one of the four key detection options; remember jsonField/jsonPointer are JSON-only
- Check for empty elements in channel model JSON/XML after hand edits
- Add a startup assertion that validates all channel definitions
When it happens
Trigger: Registering a JSON inbound channel where channelEventKeyDetection is non-null but all of getFixedValue, getJsonField, getJsonPointerExpression and getDelegateExpression return null/empty strings.
Common situations: XML/JSON channel model containing an empty <keyDetection/> element; setting a property name that does not exist (e.g. xpathField on a JSON channel); deserialization dropping the configured values due to wrong attribute names.
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 tenant detection value was not found for…
- The channel payload extractor expression for the channel…
- The channel xml key detection value was not found for the…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f65921204bbba574.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java:164
InboundEventKeyDetector<JsonNode> 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.getJsonField())) {
eventKeyDetector = new JsonFieldBasedInboundEventKeyDetector(keyDetection.getJsonField());
} else if (StringUtils.isNotEmpty(keyDetection.getJsonPointerExpression())) {
eventKeyDetector = new JsonPointerBasedInboundEventKeyDetector(keyDetection.getJsonPointerExpression(), objectMapper);
} else if (StringUtils.isNotEmpty(keyDetection.getDelegateExpression())) {
//noinspection unchecked
eventKeyDetector = resolveExpression(keyDetection.getDelegateExpression(), InboundEventKeyDetector.class);
} else {
throw new FlowableException(
"The channel json key detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, jsonField, jsonPointerExpression or 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.getJsonPointerExpression())) {
eventTenantDetector = new JsonPointerBasedInboundEventTenantDetector(channelEventTenantIdDetection.getJsonPointerExpression());
} else if (StringUtils.isNotEmpty(channelEventTenantIdDetection.getDelegateExpression())) {
//noinspection unchecked
eventTenantDetector = resolveExpression(channelEventTenantIdDetection.getDelegateExpression(), InboundEventTenantDetector.class);
} else {
throw new FlowableException(
"The channel json tenant detection value was not found for the channel model with key " + channelModel.getKey()
+ ". One of fixedValue, jsonPointerExpression, delegateExpression should be set.");
}View on GitHub (pinned to d6d39ce1c6)