flowable/flowable-engine · error · FlowableCdiException

Cannot work with cached variables in an active command.

Error message

Cannot work with cached variables in an active command.

What it means

DefaultContextAssociationManager.getCachedVariables() throws FlowableCdiException when an engine command context is active. Cached CDI-scoped variables are only valid outside commands; reading them during a command risks returning variables that do not match the engine's current variable state.

Source

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

    public Task getTask() {
        if (Context.getCommandContext() != null) {
            throw new FlowableCdiException("Cannot work with tasks in an active command.");
        }
        return getScopedAssociation().getTask();
    }

    @Override
    public void setTask(Task task) {
        if (Context.getCommandContext() != null) {
            throw new FlowableCdiException("Cannot work with tasks in an active command.");
        }
        getScopedAssociation().setTask(task);
    }

    @Override
    public Map<String, Object> getCachedVariables() {
        if (Context.getCommandContext() != null) {
            throw new FlowableCdiException("Cannot work with cached variables in an active command.");
        }
        return getScopedAssociation().getCachedVariables();
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Read variables from the DelegateExecution/DelegateTask passed into the callback (execution.getVariable / task.getVariables).
  2. Move getCachedVariables() calls outside the command, after the engine operation returns.
  3. Use RuntimeService/TaskService variable APIs with explicit executionId/taskId.
  4. Refactor custom Commands to collect variables before entering or after leaving the command.

Example fix

// before (inside a JavaDelegate)
Map<String,Object> vars = associationManager.getCachedVariables();
// after
Map<String,Object> vars = delegateExecution.getVariables();
Defensive patterns

Strategy: type-guard

Validate before calling

Map<String,Object> safeGetVars(DelegateExecution ex) {
    return org.flowable.engine.impl.context.Context.getCommandContext() != null
        ? ex.getVariables()
        : associationManager.getCachedVariables();
}

Type guard

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

Try / catch

try {
    return associationManager.getCachedVariables();
} catch (org.flowable.cdi.FlowableCdiException e) {
    return runtimeService.getVariables(executionId); // fallback to engine service
}

Prevention

When it happens

Trigger: Invoking getCachedVariables() on the CDI ContextAssociationManager from within an active command — delegates, listeners, or code executed via CommandContext (Context.getCommandContext() != null).

Common situations: Reading business-process cached variables inside a JavaDelegate; accessing CdiBusinessProcess variables from a listener or from a job/async executor thread where a command is active.

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/9968f21665075c1f. Report an issue: GitHub.