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
- Set the serializer delegate expression on the outbound channel model, e.g. .serializerDelegateExpression("${outboundEventSerializer}") pointing at an OutboundEventSerializer bean
- Alternatively change serializerType to a built-in type (e.g. "json") that does not require a delegate expression
- 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
- Whenever serializerType is "expression", always also set the delegate expression
- Prefer built-in serializer types (json/xml) unless a custom serializer is needed
- Keep an OutboundEventSerializer bean registered and documented in the app context
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
- No channel keys configured for ${execution}
- A channel key detection value is required for the channel mo
- The channel expression key detection value was not found for
- The channel expression tenant detection value was not found
- no org.flowable.app.engine.AppEngine defined in the applicat
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/53e463c036e1d99e.
Report an issue: GitHub.