flowable/flowable-engine · error · FlowableException
lazy loading outside command context for
Error message
lazy loading outside command context for
What it means
VariableScopeImpl lazily loads its variable instances on first access, which requires an active Flowable command context because it queries the persistence layer. When variables are accessed outside a command (e.g. after the command context closed, or on a detached/async thread), ensureVariableInstancesInitialized throws FlowableException 'lazy loading outside command context for <scope>'.
Source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/persistence/entity/VariableScopeImpl.java:76
protected Map<String, VariableInstance> transientVariables;
protected ELContext cachedElContext;
protected abstract Collection<VariableInstanceEntity> loadVariableInstances();
protected abstract VariableScopeImpl getParentVariableScope();
protected abstract void initializeVariableInstanceBackPointer(VariableInstance variableInstance);
protected abstract void addLoggingSessionInfo(ObjectNode loggingNode);
protected void ensureVariableInstancesInitialized() {
if (variableInstances == null) {
variableInstances = new HashMap<>();
CommandContext commandContext = Context.getCommandContext();
if (commandContext == null) {
throw new FlowableException("lazy loading outside command context for " + this);
}
Collection<VariableInstanceEntity> variableInstancesList = loadVariableInstances();
for (VariableInstanceEntity variableInstance : variableInstancesList) {
variableInstances.put(variableInstance.getName(), variableInstance);
}
}
}
/**
* Only to be used when creating a new entity, to avoid an extra call to the database.
*/
public void internalSetVariableInstances(Map<String, VariableInstanceEntity> variableInstances) {
this.variableInstances = variableInstances;
}
@Override
public Map<String, Object> getVariables() {
return collectVariables(new HashMap<>());View on GitHub (pinned to d6d39ce1c6)
Solutions
- Access variables inside the same command/transaction that loaded the execution (e.g. within the delegate or listener)
- Wrap external access in a command: managementService.executeCommand(ctx -> execution.getVariables()) and re-fetch the entity inside the command
- Re-load the execution entity inside a new command instead of using a stale/detached reference
- Avoid storing ExecutionEntity/TaskEntity references across transactions; store IDs and reload on demand
Example fix
// before
ExecutionEntity exec = ...; // captured earlier, outside command
Map<String,Object> vars = exec.getVariables(); // throws
// after
managementService.executeCommand(commandContext -> {
ExecutionEntity exec = CommandContextUtil.getExecutionEntityManager(commandContext)
.findById(executionId);
return exec.getVariables();
}); Defensive patterns
Strategy: try-catch
Validate before calling
if (org.flowable.common.engine.impl.context.Context.getCommandContext() == null) {
throw new IllegalStateException("variable access requires an active command context; wrap in executeCommand");
} Try / catch
try {
return execution.getVariables();
} catch (org.flowable.common.engine.api.FlowableException e) {
if (e.getMessage().startsWith("lazy loading outside command context")) {
return managementService.executeCommand(ctx ->
executionEntityManager.findById(executionId).getVariables());
}
throw e;
} Prevention
- Never cache ExecutionEntity/TaskEntity references across commands — store IDs and reload
- Access variables within delegates/listeners or a managementService.executeCommand block
- Avoid touching variables from async threads outside the command interceptor chain
When it happens
Trigger: Calling collectVariables, collectVariableInstances, getVariableInstance(Local), hasVariables(Local), or any getVariable call on a VariableScopeImpl (e.g. a detached ExecutionEntity) when Context.getCommandContext() returns null — after the command finished, in a different thread, or outside Flowable's command interceptor chain.
Common situations: Accessing execution/task variables after processEngine command completed; using execution objects from async threads; caching entities across command boundaries; calling variable APIs in non-command threads without wrapping in managementService.executeCommand.
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
- lazy loading outside command context for " + this
- lazy loading outside command context for
- lazy loading outside command context for
- text is null
- bytes array is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/249afa91eb52e5b4.
Report an issue: GitHub.