Skip to content

Interrupting error event sub-process leaves a null delete reason on the activities it terminates #4257

Description

@chaserb

Interrupting error event sub-process leaves a null delete reason on the activities it terminates

Version: 8.0.0, and unchanged on main as of 2026-08-12.
Database Vendor: PostgreSQL
SpringBoot: 4.1.0

Summary

When an interrupting error event sub-process catches a BpmnError, the executions it terminates are deleted with a null delete reason. ACT_HI_ACTINST.DELETE_REASON_ is therefore null on every activity it killed, making a terminated activity indistinguishable in history from one that completed normally.

Every other interrupting event sub-process start type records a reason.

Why this looks unintended

org.flowable.engine.history.DeleteReason declares EVENT_SUBPROCESS_INTERRUPTING = "event subprocess", and five sibling behaviors use it:

  • EventSubProcessTimerStartEventActivityBehavior
  • EventSubProcessMessageStartEventActivityBehavior
  • EventSubProcessSignalStartEventActivityBehavior
  • EventSubProcessEventRegistryStartEventActivityBehavior
  • EventSubProcessVariableListenerlStartEventActivityBehavior

each as DeleteReason.EVENT_SUBPROCESS_INTERRUPTING + "(" + startEvent.getId() + ")".

BoundaryEventActivityBehavior likewise records DeleteReason.BOUNDARY_EVENT_INTERRUPTING.

The error path is the only one that does not. In ErrorPropagation.executeEventHandler:

if (parentExecution.isProcessInstanceType()) {
    executionEntityManager.deleteChildExecutions(parentExecution, null, true);

ErrorPropagation never references DeleteReason at all.

This also contradicts the documented contract of the field. The javadoc for HistoricActivityInstance#getDeleteReason() reads:

Returns the delete reason for this activity, if any was set (if completed normally, no delete reason is set)

An activity terminated by this path satisfies that description in representation while being its opposite in fact.

Reproduction

This gist contains a test in the style of the existing DeleteReasonTest, which has testInterruptingBoundaryEvent but no event-sub-process equivalent. ErrorEventSubProcessDeleteReasonTest contains:

  • testInterruptingErrorEventSubProcessfails. A forked process parks one branch on a user task; the other raises a BpmnError from a start execution listener. The interrupting error event sub-process terminates the scope, and the parked branch's activity ends with getDeleteReason() == null.
  • testInterruptingBoundaryEventForComparisonpasses, showing the boundary-event path records its reason.

Impact

Any consumer building an audit or monitoring view from ACT_HI_ACTINST reports these activities as completed. In our case a user task that was destroyed by the interruption showed as "Complete" to an approver-facing audit surface, with no signal anywhere in history that it had been terminated.

ACTIVITY_CANCELLED is dispatched and is a viable hook, but it requires listening and persisting alongside history rather than reading history, which is a very different integration for what the delete-reason column already expresses everywhere else.

Suggested fix

Pass the reason the sibling behaviors pass. fix.patch is attached; both branches of executeEventHandler that delete executions currently pass null as the deleteReason argument:

executionEntityManager.deleteChildExecutions(parentExecution,
        DeleteReason.EVENT_SUBPROCESS_INTERRUPTING + "(" + event.getId() + ")", true);
...
executionEntityManager.deleteExecutionAndRelatedData(currentExecution,
        DeleteReason.EVENT_SUBPROCESS_INTERRUPTING + "(" + event.getId() + ")", false);

I have deliberately left cancelActivity alone to keep the change minimal, even though the sibling behaviors pass the interrupting start event there and this path passes null. Happy to include that too if you would prefer the paths to match exactly.

I could not find an existing report for this on the issue tracker or the forum, but I may well have missed one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions