flowable/flowable-engine · error · FlowableException
DelegateExpression inbound channel model with key ${channelM
Error message
DelegateExpression inbound channel model with key ${channelModel.key} resolved channel adapter delegate expression to ${channelAdapter} which is not of type ${InboundEventChannelAdapter.class} What it means
Thrown during channel registration when a delegate expression for an inbound channel resolves to an object that does not implement InboundEventChannelAdapter. The event registry requires the resolved bean to be the correct adapter type so it can wire the event registry and channel model into it. This is a configuration/type mismatch fail-fast check.
Source
Thrown at modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/DelegateExpressionInboundChannelModelProcessor.java:73
EventRepositoryService eventRepositoryService,
boolean fallbackToDefaultTenant) {
if (channelModel instanceof DelegateExpressionInboundChannelModel) {
registerChannelModel((DelegateExpressionInboundChannelModel) channelModel, tenantId, eventRegistry);
}
}
protected void registerChannelModel(DelegateExpressionInboundChannelModel channelModel, String tenantId, EventRegistry eventRegistry) {
String delegateExpression = channelModel.getAdapterDelegateExpression();
if (StringUtils.isNotEmpty(delegateExpression)) {
VariableContainerWrapper variableContainer = new VariableContainerWrapper(Collections.emptyMap());
variableContainer.setVariable("tenantId", tenantId);
variableContainer.setTenantId(tenantId);
Object channelAdapter = engineConfiguration.getExpressionManager()
.createExpression(delegateExpression)
.getValue(variableContainer);
if (!(channelAdapter instanceof InboundEventChannelAdapter)) {
throw new FlowableException(
"DelegateExpression inbound channel model with key " + channelModel.getKey() + " resolved channel adapter delegate expression to "
+ channelAdapter + " which is not of type " + InboundEventChannelAdapter.class);
}
channelModel.setInboundEventChannelAdapter(channelAdapter);
((InboundEventChannelAdapter) channelAdapter).setEventRegistry(eventRegistry);
((InboundEventChannelAdapter) channelAdapter).setInboundChannelModel(channelModel);
}
}
@Override
public void unregisterChannelModel(ChannelModel channelModel, String tenantId, EventRepositoryService eventRepositoryService) {
// Nothing to do
}
public HasExpressionManagerEngineConfiguration getEngineConfiguration() {
return engineConfiguration;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Make the bean referenced by the delegate expression implement org.flowable.eventregistry.api.InboundEventChannelAdapter (implement setEventRegistry and setInboundChannelModel).
- Verify the expression string points at the intended bean (e.g. ${myInboundAdapter}) and that the bean exists and is of the right type.
- Log or inspect the resolved object (it is printed in the message) and correct the bean wiring.
- If the adapter is meant for outbound traffic, use DelegateExpressionOutboundChannelModelProcessor / an outbound channel model instead.
Example fix
// before
@Bean
public Object myChannelAdapter() { return new SomeRandomService(); }
// channelModel.setChannelAdapterDelegateExpression("${myChannelAdapter}");
// after
@Bean
public InboundEventChannelAdapter myChannelAdapter() { return new MyInboundAdapter(); } Defensive patterns
Strategy: validation
Validate before calling
Object adapter = applicationContext.getBean(exprName);
if (!(adapter instanceof org.flowable.eventregistry.api.InboundEventChannelAdapter)) {
throw new IllegalStateException("Bean " + exprName + " is not an InboundEventChannelAdapter");
} Type guard
boolean isValidInboundAdapter(Object o) {
return o instanceof org.flowable.eventregistry.api.InboundEventChannelAdapter;
} Try / catch
try {
eventRegistry.registerChannelModel(channelModel);
} catch (FlowableException e) {
if (e.getMessage().contains("not of type")) {
logger.error("Channel adapter bean has wrong type: {}", e.getMessage());
}
throw e;
} Prevention
- Type adapter beans as InboundEventChannelAdapter in @Bean method return types so wiring errors surface at startup
- Keep inbound and outbound adapter beans in clearly named classes/packages
- Unit-test channel registration in a smoke test before deployment
When it happens
Trigger: Registering an inbound channel model whose channelAdapterDelegateExpression resolves (via the Flowable expression manager, e.g. a Spring bean reference) to an object of a class that does not implement InboundEventChannelAdapter, or the expression resolves to null.
Common situations: Pointing the delegate expression at the wrong Spring bean (e.g. an outbound adapter or unrelated service); refactoring the bean class so it no longer implements InboundEventChannelAdapter; typo in bean name falling back to an unexpected bean; returning null from a factory bean.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- DelegateExpression outbound channel model with key ${channel
- Can only use a collection of String elements for referencing
- Unsupported event object type: ${event.getEventObject().getC
- expected expression ${expression} to resolve to ${type} but
- expected expression ${expression} to resolve to ${type} but
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/a57765fd223b2a52.
Report an issue: GitHub.