flowable/flowable-engine · error · FlowableIllegalArgumentException
Cannot create an event-throwing event-listener, unknown impl
Error message
Cannot create an event-throwing event-listener, unknown implementation type: " + eventListener.getImplementationType()
What it means
createEventThrowingEventListener maps an event-listener's implementationType to a throwing event-listener class (signal, message, error, global signal). If the type matches none of the known ImplementationType constants, result stays null and the factory throws FlowableIllegalArgumentException. This means the BPMN declares an event-throwing listener with an implementation type the engine does not recognize.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/parser/factory/DefaultListenerFactory.java:191
BaseDelegateEventListener result = null;
if (ImplementationType.IMPLEMENTATION_TYPE_THROW_SIGNAL_EVENT.equals(eventListener.getImplementationType())) {
result = new SignalThrowingEventListener();
((SignalThrowingEventListener) result).setSignalName(eventListener.getImplementation());
((SignalThrowingEventListener) result).setProcessInstanceScope(true);
} else if (ImplementationType.IMPLEMENTATION_TYPE_THROW_GLOBAL_SIGNAL_EVENT.equals(eventListener.getImplementationType())) {
result = new SignalThrowingEventListener();
((SignalThrowingEventListener) result).setSignalName(eventListener.getImplementation());
((SignalThrowingEventListener) result).setProcessInstanceScope(false);
} else if (ImplementationType.IMPLEMENTATION_TYPE_THROW_MESSAGE_EVENT.equals(eventListener.getImplementationType())) {
result = new MessageThrowingEventListener();
((MessageThrowingEventListener) result).setMessageName(eventListener.getImplementation());
} else if (ImplementationType.IMPLEMENTATION_TYPE_THROW_ERROR_EVENT.equals(eventListener.getImplementationType())) {
result = new ErrorThrowingEventListener();
((ErrorThrowingEventListener) result).setErrorCode(eventListener.getImplementation());
}
if (result == null) {
throw new FlowableIllegalArgumentException("Cannot create an event-throwing event-listener, unknown implementation type: " + eventListener.getImplementationType());
}
result.setEntityClass(getEntityType(eventListener.getEntityType()));
return result;
}
@Override
public CustomPropertiesResolver createClassDelegateCustomPropertiesResolver(FlowableListener listener) {
return classDelegateFactory.create(listener.getCustomPropertiesResolverImplementation(), null);
}
@Override
public CustomPropertiesResolver createExpressionCustomPropertiesResolver(FlowableListener listener) {
return new ExpressionCustomPropertiesResolver(expressionManager.createExpression(listener.getCustomPropertiesResolverImplementation()));
}
@Override
public CustomPropertiesResolver createDelegateExpressionCustomPropertiesResolver(FlowableListener listener) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set implementationType to one of the supported throwing types: throwSignalEvent, throwGlobalSignalEvent, throwMessageEvent, or throwErrorEvent.
- Check the BPMN XML for typos or empty implementationType values on eventListener elements.
- If the listener should invoke code rather than throw an event, use implementationType class or delegate-expression instead.
- Consult the ImplementationType constants in your Flowable version to confirm valid values.
Example fix
// before <flowable:eventListener events="JOB_EXECUTION_SUCCESS" implementationType="throwSgnalEvent" signalName="done" /> // after <flowable:eventListener events="JOB_EXECUTION_SUCCESS" implementationType="throwSignalEvent" signalName="done" />
Defensive patterns
Strategy: validation
Validate before calling
Set<String> valid = Set.of(ImplementationType.IMPLEMENTATION_TYPE_THROW_SIGNAL_EVENT,
ImplementationType.IMPLEMENTATION_TYPE_THROW_GLOBAL_SIGNAL_EVENT,
ImplementationType.IMPLEMENTATION_TYPE_THROW_MESSAGE_EVENT,
ImplementationType.IMPLEMENTATION_TYPE_THROW_ERROR_EVENT);
if (!valid.contains(eventListener.getImplementationType())) {
throw new IllegalArgumentException("unsupported event-throwing implementationType: "
+ eventListener.getImplementationType());
} Type guard
boolean isThrowingType = type != null && (type.startsWith("throw-signal")
|| type.startsWith("throw-global-signal")
|| type.startsWith("throw-message")
|| type.startsWith("throw-error")); Try / catch
try {
deploymentBuilder.deploy();
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot create an event-throwing event-listener")) {
// correct the implementationType attribute and redeploy
} else { throw e; }
} Prevention
- Only use the ImplementationType constants, never hand-typed strings.
- Spell-check implementationType attributes in BPMN XML; values are case-sensitive.
- Remember event-throwing listeners accept only the four throwing types, not class/expression.
When it happens
Trigger: A <flowable:eventListener> whose implementationType attribute is misspelled, empty, or set to a non-event-throwing type (e.g. class/delegate-expression style values) while the factory is invoked for event-throwing listener creation.
Common situations: Typos in the implementationType attribute in BPMN XML; using an implementation type valid for regular listeners but not for event-throwing listeners; upgrades where an implementation type was removed or renamed.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unsupported entity-type for a FlowableEventListener: " + ent
- No execution context active and event (" + event + ") is not
- Cannot throw process-instance scoped message, since the disp
- Cannot throw process-instance scoped signal, since the dispa
- BPMN XSD could not be found
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/409b4786cd4236f5.
Report an issue: GitHub.