Environment (Required on creation):
- potentially all supported Camunda versions
- all distros
- all databases
Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):
- Job execution for an async-before process-level start event fails if a message was correlated in-between to a non-interrupting message start event in an event subprocess that runs into a transaction boundary in that subprocess in the same process instance
- Stacktrace for the job:
2021-10-07T04:22:01,271+0000-[ERROR]-[cid=,tid=,clu=]-[context]-[160 ]-ENGINE-16004 Exception while closing command context: nulljava.lang.NullPointerException: null at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationProcessStart$2.callback(PvmAtomicOperationProcessStart.java:76) at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationProcessStart$2.callback(PvmAtomicOperationProcessStart.java:72) at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueIfExecutionDoesNotAffectNextOperation(PvmExecutionImpl.java:2039) at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationProcessStart.eventNotificationsCompleted(PvmAtomicOperationProcessStart.java:66) at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationProcessStart.eventNotificationsCompleted(PvmAtomicOperationProcessStart.java:32) at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:66) at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:118) at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:76) at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:81) at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:40) at org.camunda.bpm.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:134) at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:110) at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:43) at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:28) at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:110) at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:72) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:70) at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:70) at org.camunda.bpm.engine.impl.interceptor.CommandCounterInterceptor.execute(CommandCounterInterceptor.java:35) at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33) at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:57) at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:110) at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:71) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
Steps to reproduce (Required on creation):
- Create a process with a start event with async-before and exclusive.
- Add an event subprocess with a non-interrupting message start event and a follow-up activity that creates a transaction boundary (e.g., an external task) in that subprocess.
- Disable the job executor
- Start an instance of the process
- Correlate the message to the event subprocess of the new instance
- Run the job for the process instance
Observed Behavior (Required on creation):
The job fails with the described stacktrace
Expected behavior (Required on creation):
The job executes successfully and performs all follow-up activities as expected
Root Cause (Required on prioritization):
- A process instance is created, one execution is waiting on the start event, the execution reaches a transaction boundary due to async-before on the start event
- Due to the correlation of a message to a non-interrupting message start event in an event subprocess, the process instance creates a concurrent execution for the event subprocess
- The execution waiting on the process instance start event will be moved into another concurrent execution, referencing the process instance execution as a parent
- The event subprocess reaches a transaction boundary as well due to an external task
- The job executor executes the process instance start event inside the second concurrent execution
- The PvmAtomicOperationProcessStart operation wants to complete and continue. Due to PvmAtomicOperationProcessStart, it needs to fetch the process instance start context.
- For that, it needs to run inside the execution of the process instance. This is checked in the ExecutionEntity.
- Since the start event is now however run inside the second concurrent execution and not the process instance execution anymore, no process instance start context is returned and the job execution fails in PvmAtomicOperationProcessStart.