flowable/flowable-engine · error · FlowableException

The channel key ${outboundChannelModel.key} is using express

Error message

The channel key ${outboundChannelModel.key} is using expression deserialization, but pipelineDelegateExpression was not set.

What it means

Outbound channels with serializerType "expression" must supply a serializerDelegateExpression that resolves to an OutboundEventSerializer used by DefaultOutboundEventProcessingPipeline. When that expression is missing/empty, OutboundChannelModelProcessor.registerChannelModel throws this error because no pipeline can be built for serializing outbound event payloads.

Source

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

            if (StringUtils.isNotEmpty(outboundChannelModel.getPipelineDelegateExpression())) {
                eventProcessingPipeline = resolveExpression(outboundChannelModel.getPipelineDelegateExpression(), OutboundEventProcessingPipeline.class);
                
            } else if ("json".equals(outboundChannelModel.getSerializerType())) {
                OutboundEventSerializer eventSerializer = new EventPayloadToJsonStringSerializer(objectMapper);
                eventProcessingPipeline = new DefaultOutboundEventProcessingPipeline(eventSerializer);
                
            } else if ("xml".equals(outboundChannelModel.getSerializerType())) {
                OutboundEventSerializer eventSerializer = new EventPayloadToXmlStringSerializer();
                eventProcessingPipeline = new DefaultOutboundEventProcessingPipeline(eventSerializer);
                
            } else if ("expression".equals(outboundChannelModel.getSerializerType())) {
                if (StringUtils.isNotEmpty(outboundChannelModel.getSerializerDelegateExpression())) {
                    OutboundEventSerializer outboundEventSerializer = resolveExpression(
                            outboundChannelModel.getSerializerDelegateExpression(), OutboundEventSerializer.class);
                    eventProcessingPipeline = new DefaultOutboundEventProcessingPipeline(outboundEventSerializer);
                } else {
                    throw new FlowableException(
                        "The channel key " + outboundChannelModel.getKey()
                            + " is using expression deserialization, but pipelineDelegateExpression was not set.");
                }
            }  else {
                eventProcessingPipeline = null;
            }

            if (eventProcessingPipeline != null) {
                outboundChannelModel.setOutboundEventProcessingPipeline(eventProcessingPipeline);
            }

        }
    }

    protected <T> T resolveExpression(String expression, Class<T> type) {
        Object value = CommandContextUtil.getEventRegistryConfiguration().getExpressionManager()
            .createExpression(expression)
            .getValue(new VariableContainerWrapper(Collections.emptyMap()));

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set the serializer delegate expression on the outbound channel model, e.g. .serializerDelegateExpression("${outboundEventSerializer}") pointing at an OutboundEventSerializer bean
  2. Alternatively change serializerType to a built-in type (e.g. "json") that does not require a delegate expression
  3. Register an OutboundEventSerializer bean in the application context and confirm the expression string matches its bean name

Example fix

// before
OutboundChannelModelBuilder b = eventRepositoryService.createOutboundChannelModelBuilder()
    .key("out-channel")
    .serializerExpressionType(); // no delegate expression set
// after
OutboundChannelModelBuilder b = eventRepositoryService.createOutboundChannelModelBuilder()
    .key("out-channel")
    .serializerExpressionType()
    .serializerDelegateExpression("${jsonOutboundEventSerializer}");
Defensive patterns

Strategy: validation

Validate before calling

if ("expression".equals(outboundChannelModel.getSerializerType()) && isEmpty(outboundChannelModel.getSerializerDelegateExpression())) {
    throw new IllegalArgumentException("Outbound channel '" + outboundChannelModel.getKey() + "' needs serializerDelegateExpression");
}

Try / catch

try {
    registerChannelModel(...);
} catch (FlowableException e) {
    if (e.getMessage().contains("pipelineDelegateExpression was not set")) {
        // set serializerDelegateExpression or switch serializerType
    } else { throw e; }
}

Prevention

When it happens

Trigger: registerChannelModel on an outbound channel whose getSerializerType() equals "expression" while getSerializerDelegateExpression() is empty or null.

Common situations: Setting serializerType to "expression" in channel config but forgetting the delegate expression attribute; switching serializer type from "json" to "expression" without adding the bean reference; channel model builder call setting serializerExpression type without the expression value.

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/53e463c036e1d99e. Report an issue: GitHub.