flowable/flowable-engine · error · BpmnError

${errorCode}

${errorCode}

Error message

No catching boundary event found for error with errorCode '${errorCode}', neither in same process nor in parent process

What it means

Raised as a BpmnError when an error is propagated (ErrorPropagation.propagateError) but neither the current process instance's activities nor any parent (call-activity) process contains a catching error boundary event / error event handler for the given errorCode. The error has nowhere to go, so the engine aborts.

Solutions

  1. Add an error boundary event (or error start event in an event subprocess) that catches the thrown errorCode on the appropriate activity
  2. Fix errorCode/errorRef mismatches (names are matched exactly) between thrower and catcher
  3. Ensure the parent process's call activity has a boundary error event when errors should cross the call boundary
  4. Declare a shared <error> element in the process definitions and reference it consistently

Example fix

// before
<serviceTask id="t" flowable:class="X"/> <!-- no error catch -->
// after
<boundaryEvent id="catchErr" attachedToRef="t">
  <errorEventDefinition errorRef="myError"/>
</boundaryEvent>
Defensive patterns

Strategy: validation

Validate before calling

// before deploy: assert every thrown errorCode has a catcher
Set<String> thrown = setOf("myError");
Set<String> caught = collectErrorRefs(bpmnModel); // errorRefs on boundary/error-start events
if (!caught.containsAll(thrown)) throw new IllegalStateException("uncatched error codes: " + thrown);
if (!caught.containsAll(thrown)) throw new IllegalStateException("uncatched error codes: " + thrown);

Try / catch

try {
    runtimeService.trigger(executionId);
} catch (org.activiti.engine.delegate.BpmnError e) {
    logger.error("Unhandled BPMN error: {}", e.getErrorCode());
    throw e;
}

Prevention

When it happens

Trigger: An error end event or ErrorThrowingEventListener throws errorCode X while no boundary error event, error event subprocess, or parent-process handler catches X anywhere up the execution hierarchy.

Common situations: Typo or case mismatch between the thrown errorCode and the boundaryEvent's errorRef; boundary event attached to the wrong activity; missing error boundary on the call activity in the parent process; error event subprocess absent.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ErrorPropagation.java:82

        while (execution != null) {
            String eventHandlerId = findLocalErrorEventHandler(execution, errorCode);
            if (eventHandlerId != null) {
                executeCatch(eventHandlerId, execution, errorCode);
                break;
            }

            if (execution.isProcessInstanceType()) {
                // dispatch process completed event
                if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
                    Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
                            ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT, execution),
                            EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);
                }
            }
            execution = getSuperExecution(execution);
        }
        if (execution == null) {
            throw new BpmnError(errorCode, "No catching boundary event found for error with errorCode '"
                    + errorCode + "', neither in same process nor in parent process");
        }
    }

    private static String findLocalErrorEventHandler(ActivityExecution execution, String errorCode) {
        PvmScope scope = execution.getActivity();
        while (scope != null) {

            @SuppressWarnings("unchecked")
            List<ErrorEventDefinition> definitions = (List<ErrorEventDefinition>) scope.getProperty(BpmnParse.PROPERTYNAME_ERROR_EVENT_DEFINITIONS);
            if (definitions != null) {
                // definitions are sorted by precedence, ie. event subprocesses first.
                for (ErrorEventDefinition errorEventDefinition : definitions) {
                    if (errorEventDefinition.catches(errorCode)) {
                        return scope.findActivity(errorEventDefinition.getHandlerActivityId()).getId();
                    }
                }
            }

View on GitHub (pinned to d6d39ce1c6)