flowable/flowable-engine · error · FlowableException

A channel key detection value is required for inbound…

Error message

A channel key detection value is required for inbound channel ${channelModel.key}

What it means

Thrown when building a JSON event processing pipeline: an inbound channel model has no ChannelEventKeyDetection configured. The pipeline needs a key detector to map an incoming JSON event to a registered event definition, so registration cannot proceed without one.

Solutions

  1. Set a ChannelEventKeyDetection on the channel model with one of: fixedValue, jsonField, jsonPointerExpression, or delegateExpression.
  2. If the key is static per channel, use keyDetection.setFixedValue("my.event.key").
  3. If the key lives in a JSON field, use keyDetection.setJsonField("type").
  4. For dynamic detection, set keyDetection.setDelegateExpression("${myKeyDetector}") pointing at an InboundEventKeyDetector bean.

Example fix

// before
InboundChannelModel channelModel = new InboundChannelModel();
channelModel.setKey("jsonChannel");

// after
ChannelEventKeyDetection keyDetection = new ChannelEventKeyDetection();
keyDetection.setJsonField("type");
channelModel.setChannelEventKeyDetection(keyDetection);
Defensive patterns

Strategy: validation

Validate before calling

if (channelModel.getChannelEventKeyDetection() == null) {
    throw new IllegalArgumentException("Channel " + channelModel.getKey() + " needs a keyDetection");
}

Type guard

null

Try / catch

try {
    eventRegistry.registerChannelModel(channelModel);
} catch (FlowableException e) {
    if (e.getMessage().contains("channel key detection value is required")) {
        logger.error("Add keyDetection to channel {}", channelModel.getKey());
    }
    throw e;
}

Prevention

When it happens

Trigger: Registering a JSON inbound channel model (deserializeContentType application/json) where channelModel.getChannelEventKeyDetection() returns null — i.e. no keyDetection element/property set on the channel model.

Common situations: Hand-built InboundChannelModel missing setChannelEventKeyDetection; channel JSON/YAML model omitting the keyDetection section; copying a channel definition and dropping the key detection block.

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/5f4b514e97ab483e. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java:151

        }

        InboundEventTenantDetector<JsonNode> eventTenantDetector = null; // By default no multi-tenancy is applied

        JsonFieldToMapPayloadExtractor jsonFieldToMapPayloadExtractor = new JsonFieldToMapPayloadExtractor(engineConfiguration.getJsonPayloadValueTransformer());
        InboundEventPayloadExtractor<JsonNode> eventPayloadExtractor = createInboundEventPayloadExtractor(channelModel, jsonFieldToMapPayloadExtractor);

        InboundEventTransformer eventTransformer;
        if (StringUtils.isEmpty(channelModel.getEventTransformerDelegateExpression())) {
            eventTransformer = new DefaultInboundEventTransformer();
        } else {
            eventTransformer = resolveExpression(channelModel.getEventTransformerDelegateExpression(), InboundEventTransformer.class);
        }

        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();

View on GitHub (pinned to d6d39ce1c6)