flowable/flowable-engine · error · FlowableCdiException

Cannot work with scoped associations inside command context.

Error message

Cannot work with scoped associations inside command context.

What it means

setExecution() refuses to change the scoped association while code is executing inside a Flowable command context (Context.getCommandContext() != null). Scoped associations are CDI-side state manipulated by application code; the engine already manages its own execution context, so touching the association from within a command (e.g. inside a JavaDelegate or event listener) is considered a programming error.

Solutions

  1. Do not call BusinessProcess association APIs from engine callbacks; use Context.getProcessVariables / delegate execution APIs inside delegates.
  2. If CDI integration is needed in delegates, use the flowable-cdi CommandContext handling (BusinessProcess can read variables via Context) but defer association changes to after the command completes.
  3. Move the association logic to application-managed code outside the engine invocation.

Example fix

// before
class MyDelegate implements JavaDelegate {
  public void execute(DelegateExecution ex) { businessProcess.associateExecution(...); }
}
// after
class MyDelegate implements JavaDelegate {
  public void execute(DelegateExecution ex) { ex.setVariable("k", v); }
}
Defensive patterns

Strategy: validation

Validate before calling

if (org.flowable.engine.impl.context.Context.getCommandContext() != null) {
    throw new IllegalStateException("Do not use BusinessProcess inside a command context");
}

Type guard

static boolean inCommandContext() { return org.flowable.engine.impl.context.Context.getCommandContext() != null; }

Try / catch

try { businessProcess.associateExecution(e); } catch (FlowableCdiException e) { /* inside engine callback; use DelegateExecution APIs instead */ }

Prevention

When it happens

Trigger: Calling BusinessProcess.associateExecution/setExecution (or methods that internally re-associate) from within a JavaDelegate, TaskListener, ExecutionListener, or other engine callback that runs inside a command.

Common situations: Trying to use CDI-injected BusinessProcess inside a service task delegate; using BusinessProcess in an async job executor thread that still has an open command context.

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/4be6e1de855ec513. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-cdi/src/main/java/org/flowable/cdi/impl/context/DefaultContextAssociationManager.java:149

    protected List<Class<? extends ScopedAssociation>> getAvailableScopedAssociationClasses() {
        ArrayList<Class<? extends ScopedAssociation>> scopeTypes = new ArrayList<>();
        scopeTypes.add(ConversationScopedAssociation.class);
        scopeTypes.add(RequestScopedAssociation.class);
        return scopeTypes;
    }

    protected ScopedAssociation getScopedAssociation() {
        return ProgrammaticBeanLookup.lookup(getBroadestActiveContext(), beanManager);
    }

    @Override
    public void setExecution(Execution execution) {
        if (execution == null) {
            throw new FlowableCdiException("Cannot associate with execution: null");
        }

        if (Context.getCommandContext() != null) {
            throw new FlowableCdiException("Cannot work with scoped associations inside command context.");
        }

        ScopedAssociation scopedAssociation = getScopedAssociation();
        Execution associatedExecution = scopedAssociation.getExecution();
        if (associatedExecution != null && !associatedExecution.getId().equals(execution.getId())) {
            throw new FlowableCdiException("Cannot associate " + execution + ", already associated with " + associatedExecution + ". Disassociate first!");
        }

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Associating {} (@{})", execution, scopedAssociation.getClass().getAnnotations()[0].annotationType().getSimpleName());
        }
        scopedAssociation.setExecution(execution);
    }

    @Override
    public void disAssociate() {
        if (Context.getCommandContext() != null) {
            throw new FlowableCdiException("Cannot work with scoped associations inside command context.");

View on GitHub (pinned to d6d39ce1c6)