flowable/flowable-engine · error · ActivitiIllegalArgumentException

type is null

Error message

type is null

What it means

ActivitiEventImpl is the base class of all engine events; its constructor requires a FlowableEngineEventType and rejects null with ActivitiIllegalArgumentException("type is null"). The event type drives listener dispatch, so an event without a type cannot be routed.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/delegate/event/impl/ActivitiEventImpl.java:46

    protected FlowableEngineEventType type;
    protected String executionId;
    protected String processInstanceId;
    protected String processDefinitionId;

    /**
     * Creates a new event implementation, not part of an execution context.
     */
    public ActivitiEventImpl(FlowableEngineEventType type) {
        this(type, null, null, null);
    }

    /**
     * Creates a new event implementation, part of an execution context.
     */
    public ActivitiEventImpl(FlowableEngineEventType type, String executionId, String processInstanceId,
            String processDefinitionId) {
        if (type == null) {
            throw new ActivitiIllegalArgumentException("type is null");
        }
        this.type = type;
        this.executionId = executionId;
        this.processInstanceId = processInstanceId;
        this.processDefinitionId = processDefinitionId;
    }

    @Override
    public FlowableEngineEventType getType() {
        return type;
    }

    public void setType(FlowableEngineEventType type) {
        this.type = type;
    }

    public String getExecutionId() {
        return executionId;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a concrete FlowableEngineEventType constant (e.g. FlowableEngineEventType.PROCESS_STARTED).
  2. Validate/normalize the type lookup before constructing the event, falling back to a known default.
  3. Ensure custom dispatchers use ActivitiEventBuilder factory methods which never pass null types.

Example fix

// before
FlowableEngineEventType type = TYPE_MAP.get(eventName);
new ActivitiEventImpl(type, execId, procId, defId); // type may be null
// after
FlowableEngineEventType type = TYPE_MAP.getOrDefault(eventName, FlowableEngineEventType.CUSTOM);
new ActivitiEventImpl(type, execId, procId, defId);
Defensive patterns

Strategy: validation

Validate before calling

if (type == null) type = FlowableEngineEventType.CUSTOM;

Type guard

FlowableEngineEventType safeType(FlowableEngineEventType t) { return t != null ? t : FlowableEngineEventType.CUSTOM; }

Try / catch

try { dispatcher.dispatchEvent(new ActivitiEventImpl(type, e1, e2, e3)); } catch (ActivitiIllegalArgumentException e) { logger.error("Event type null", e); }

Prevention

When it happens

Trigger: new ActivitiEventImpl(null, executionId, processInstanceId, processDefinitionId) or a subclass/builder call passing a null FlowableEngineEventType (e.g. a computed type variable that resolved to null).

Common situations: Custom listeners building events with a type looked up from a map or switch that returned null; mapping unknown event names to types; hand-written event constructors in tests.

Related errors


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