flowable/flowable-engine · error · PvmException

not in a transition scope

Error message

not in a transition scope

What it means

PvmException thrown by the single-argument executionListener(...) when the builder is not currently inside a transition (the internal 'transition' cursor is null). Adding an execution listener with this overload only makes sense immediately after startTransition(...). It is a builder-state (scope) violation.

Solutions

  1. Call this overload only directly after startTransition(...) and before starting another activity or transition.
  2. Use the two-argument executionListener(eventName, listener) when you are in an activity or process scope.
  3. Reorder the builder calls so the listener is added while the transition is the current element.

Example fix

// before
builder.startActivity("a");
builder.executionListener(myListener); // wrong scope
// after
builder.startActivity("a").startTransition("b").executionListener(myListener);
Defensive patterns

Strategy: validation

Validate before calling

// only valid immediately after startTransition(...); track builder state yourself
boolean inTransition = lastBuilderCallWasStartTransition;
if (!inTransition) {
  throw new IllegalStateException("executionListener(listener) requires an open transition scope");
}
builder.executionListener(listener);

Try / catch

try {
  builder.executionListener(listener);
} catch (PvmException e) {
  throw new IllegalStateException("Call executionListener(listener) directly after startTransition()", e);
}

Prevention

When it happens

Trigger: Calling executionListener(listener) before any startTransition(...) call, or after a subsequent startActivity(...) call that changed the current scope.

Common situations: Builder DSL misuse: adding a transition-scoped listener at the wrong point in the fluent call chain, e.g. after switching back to an activity or process scope.

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/9259b30e4e2dfe40. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/ProcessDefinitionBuilder.java:141

            transition.setDestination(destination);
        }
        return processDefinition;
    }

    protected ActivityImpl getActivity() {
        return (ActivityImpl) scopeStack.peek();
    }

    public ProcessDefinitionBuilder scope() {
        getActivity().setScope(true);
        return this;
    }

    public ProcessDefinitionBuilder executionListener(ExecutionListener executionListener) {
        if (transition != null) {
            transition.addExecutionListener(executionListener);
        } else {
            throw new PvmException("not in a transition scope");
        }
        return this;
    }

    public ProcessDefinitionBuilder executionListener(String eventName, ExecutionListener executionListener) {
        if (transition == null) {
            scopeStack.peek().addExecutionListener(eventName, executionListener);
        } else {
            throw new PvmException("not in an activity- or process definition scope. (but in a transition scope)");
        }
        return this;
    }
}

View on GitHub (pinned to d6d39ce1c6)