{"record":{"id":"82bc3977c0ef6ad8","repo":"flowable/flowable-engine","slug":"didn-t-expect-active-execution-in-activity-bug","errorCode":null,"errorMessage":"didn't expect active execution in ${activity}. bug?","messagePattern":"didn't expect active execution in (.+?)\\. bug\\?","errorType":"exception","errorClass":"PvmException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/runtime/ExecutionImpl.java","lineNumber":611,"sourceCode":"        performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_END);\n    }\n\n    @Override\n    public void executeActivity(PvmActivity activity) {\n        setActivity((ActivityImpl) activity);\n        performOperation(AtomicOperation.ACTIVITY_START);\n    }\n\n    @Override\n    public List<ActivityExecution> findInactiveConcurrentExecutions(PvmActivity activity) {\n        List<ActivityExecution> inactiveConcurrentExecutionsInActivity = new ArrayList<>();\n        List<ActivityExecution> otherConcurrentExecutions = new ArrayList<>();\n        if (isConcurrent()) {\n            List<? extends ActivityExecution> concurrentExecutions = getParent().getExecutions();\n            for (ActivityExecution concurrentExecution : concurrentExecutions) {\n                if (concurrentExecution.getActivity() != null && concurrentExecution.getActivity().getId().equals(activity.getId())) {\n                    if (concurrentExecution.isActive()) {\n                        throw new PvmException(\"didn't expect active execution in \" + activity + \". bug?\");\n                    }\n                    inactiveConcurrentExecutionsInActivity.add(concurrentExecution);\n                } else {\n                    otherConcurrentExecutions.add(concurrentExecution);\n                }\n            }\n        } else {\n            if (!isActive()) {\n                inactiveConcurrentExecutionsInActivity.add(this);\n            } else {\n                otherConcurrentExecutions.add(this);\n            }\n        }\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"inactive concurrent executions in '{}': {}\", activity, inactiveConcurrentExecutionsInActivity);\n            LOGGER.debug(\"other concurrent executions: {}\", otherConcurrentExecutions);\n        }\n        return inactiveConcurrentExecutionsInActivity;","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/runtime/ExecutionImpl.java#L593-L629","documentation":"A PvmException raised by ExecutionImpl.findInactiveConcurrentExecutions when, while joining a concurrent activity, another concurrent execution is still ACTIVE in that same activity. The message ends with 'bug?' because the PVM expects executions found in the target activity to already be inactive (waiting). Encountering it means the concurrency/join invariant of the execution tree was violated.","triggerScenarios":"A concurrent (fork/join) activity is entered while a sibling concurrent execution is still actively executing the same activity; usually from incorrect custom concurrency behaviors, or signalling/racing executions so two active executions land on the same node.","commonSituations":"Faulty custom parallel-gateway/join implementations; race conditions with async continuations joining on one activity; ported Activiti 4-era custom behaviors incompatible with the Flowable execution model.","solutions":["Treat as a likely engine/behavior bug: capture the process definition, activity id and stack trace for a bug report","Review custom concurrency behaviors for calls that leave executions active in a join activity","Check async/job-executor configuration that could let two executions run the join node concurrently","Avoid signalling an execution whose sibling has not yet reached the join"],"exampleFix":"// before\n// custom behavior marks execution active after take, join sees it active\nexecution.setActive(true);\nexecution.take(transition);\n// after\nexecution.take(transition); // let the PVM manage activity/active state on transition","handlingStrategy":"try-catch","validationCode":"// before signalling, confirm no sibling is still active in the join activity\nlong active = runtimeService.createExecutionQuery()\n    .processInstanceId(pid).activityId(joinActivityId).list().stream()\n    .filter(Execution::isActive).count();\nif (active > 0) { /* wait or handle */ }","typeGuard":null,"tryCatchPattern":"try {\n  runtimeService.signal(executionId);\n} catch (PvmException e) {\n  if (e.getMessage().contains(\"didn't expect active execution\")) {\n    log.error(\"join invariant violated — likely engine/behavior bug\", e);\n  }\n}","preventionTips":["Use built-in parallel/inclusive gateways rather than custom join logic","Avoid racing async jobs into the same join activity","Report reproducible cases to the Flowable project with stack trace"],"tags":["process-engine","concurrency","invariant-violation"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}