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

  1. Set implementationType to one of the supported throwing types: throwSignalEvent, throwGlobalSignalEvent, throwMessageEvent, or throwErrorEvent.
  2. Check the BPMN XML for typos or empty implementationType values on eventListener elements.
  3. If the listener should invoke code rather than throw an event, use implementationType class or delegate-expression instead.
  4. 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

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


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