flowable/flowable-engine · error · FlowableException

Cannot trigger ${execution} : the activityBehavior ${activit

Error message

Cannot trigger ${execution} : the activityBehavior ${activityBehavior.getClass()} does not implement the org.flowable.engine.impl.delegate.TriggerableActivityBehavior interface

What it means

TriggerExecutionOperation.run resumes a waiting execution (e.g. after signal/message/trigger). The current flow element's behavior must implement TriggerableActivityBehavior to be triggered; if it does not, the engine cannot continue the execution and throws this FlowableException.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/TriggerExecutionOperation.java:72

            ActivityBehavior activityBehavior = (ActivityBehavior) ((FlowNode) currentFlowElement).getBehavior();
            if (activityBehavior instanceof TriggerableActivityBehavior) {

                if (!triggerAsync) {
                    ((TriggerableActivityBehavior) activityBehavior).trigger(execution, null, null);
                    
                } else {
                    ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
                    JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService();
                    JobEntity job = JobUtil.createJob(execution, currentFlowElement, AsyncTriggerJobHandler.TYPE, processEngineConfiguration);

                    jobService.createAsyncJob(job, true);
                    jobService.scheduleAsyncJob(job);
                }


            } else {
                throw new FlowableException("Cannot trigger " + execution
                    + " : the activityBehavior " + activityBehavior.getClass() + " does not implement the "
                    + TriggerableActivityBehavior.class.getName() + " interface");

            }

        } else if (currentFlowElement == null) {
            throw new FlowableException("Cannot trigger " + execution
                    + " : no current flow element found. Check the execution id that is being passed "
                    + "(it should not be a process instance execution, but a child execution currently referencing a flow element).");

        } else {
            throw new FlowableException("Programmatic error: cannot trigger " + execution + ", invalid flow element type found: "
                    + currentFlowElement.getClass().getName() + ".");

        }
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Query the execution and verify its activityId is a waiting state (receive task, intermediate catch event) before triggering
  2. Ensure custom ActivityBehaviors implement TriggerableActivityBehavior when they must be triggerable
  3. Guard against double-triggers with an optimistic-lock/race check
  4. Use event subscription queries (signalEventReceived/messageEventReceived) instead of raw trigger when appropriate

Example fix

// before
Execution e = runtimeService.createExecutionQuery().processInstanceId(pid).singleResult();
runtimeService.trigger(e.getId());
// after
Execution e = runtimeService.createExecutionQuery()
    .processInstanceId(pid)
    .activityId("waitReceiveTask")
    .singleResult();
if (e != null) {
    runtimeService.trigger(e.getId());
}
Defensive patterns

Strategy: validation

Validate before calling

Execution e = runtimeService.createExecutionQuery()
    .processInstanceId(pid)
    .activityId("waitForSignal")
    .singleResult();
if (e == null) {
    throw new IllegalStateException("Execution not waiting at waitForSignal");
}
runtimeService.trigger(e.getId());

Type guard

boolean isWaitingAtTriggerable(Execution e, String activityId) {
    return e != null && activityId.equals(e.getActivityId());
}

Try / catch

try {
    runtimeService.trigger(executionId);
} catch (FlowableException e) {
    if (e.getMessage().contains("does not implement") && e.getMessage().contains("TriggerableActivityBehavior")) {
        log.error("Execution {} is not at a triggerable activity; re-check query", executionId);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling runtimeService.trigger(executionId) (or signal/message received) on an execution whose current activity behavior is not TriggerableActivityBehavior — e.g. triggering the wrong execution id, or an execution parked on a non-waiting element.

Common situations: Triggering an execution selected by the wrong query (not actually waiting at a receive task/user task); race conditions where the execution already moved on; custom behaviors not implementing the right interface.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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