flowable/flowable-engine · error · PvmException

didn't expect active execution in

Error message

didn't expect active execution in ${activity}. bug?

What it means

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.

Solutions

  1. Treat as a likely engine/behavior bug: capture the process definition, activity id and stack trace for a bug report
  2. Review custom concurrency behaviors for calls that leave executions active in a join activity
  3. Check async/job-executor configuration that could let two executions run the join node concurrently
  4. Avoid signalling an execution whose sibling has not yet reached the join

Example fix

// before
// custom behavior marks execution active after take, join sees it active
execution.setActive(true);
execution.take(transition);
// after
execution.take(transition); // let the PVM manage activity/active state on transition
Defensive patterns

Strategy: try-catch

Validate before calling

// before signalling, confirm no sibling is still active in the join activity
long active = runtimeService.createExecutionQuery()
    .processInstanceId(pid).activityId(joinActivityId).list().stream()
    .filter(Execution::isActive).count();
if (active > 0) { /* wait or handle */ }

Try / catch

try {
  runtimeService.signal(executionId);
} catch (PvmException e) {
  if (e.getMessage().contains("didn't expect active execution")) {
    log.error("join invariant violated — likely engine/behavior bug", e);
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/runtime/ExecutionImpl.java:611

        performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_END);
    }

    @Override
    public void executeActivity(PvmActivity activity) {
        setActivity((ActivityImpl) activity);
        performOperation(AtomicOperation.ACTIVITY_START);
    }

    @Override
    public List<ActivityExecution> findInactiveConcurrentExecutions(PvmActivity activity) {
        List<ActivityExecution> inactiveConcurrentExecutionsInActivity = new ArrayList<>();
        List<ActivityExecution> otherConcurrentExecutions = new ArrayList<>();
        if (isConcurrent()) {
            List<? extends ActivityExecution> concurrentExecutions = getParent().getExecutions();
            for (ActivityExecution concurrentExecution : concurrentExecutions) {
                if (concurrentExecution.getActivity() != null && concurrentExecution.getActivity().getId().equals(activity.getId())) {
                    if (concurrentExecution.isActive()) {
                        throw new PvmException("didn't expect active execution in " + activity + ". bug?");
                    }
                    inactiveConcurrentExecutionsInActivity.add(concurrentExecution);
                } else {
                    otherConcurrentExecutions.add(concurrentExecution);
                }
            }
        } else {
            if (!isActive()) {
                inactiveConcurrentExecutionsInActivity.add(this);
            } else {
                otherConcurrentExecutions.add(this);
            }
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("inactive concurrent executions in '{}': {}", activity, inactiveConcurrentExecutionsInActivity);
            LOGGER.debug("other concurrent executions: {}", otherConcurrentExecutions);
        }
        return inactiveConcurrentExecutionsInActivity;

View on GitHub (pinned to d6d39ce1c6)