flowable/flowable-engine · error · ActivitiException
lazy loading outside command context
Error message
lazy loading outside command context
What it means
VariableScopeImpl.ensureVariableInstancesInitialized initializes the scope's variable map by loading all variable instances from the database, which requires an active CommandContext. When a variable-scope entity (Execution/Task) is accessed outside engine command execution, initialization is impossible and the engine throws this ActivitiException to prevent silent data corruption. This is the shared guard behind lazy variable loading for all scopes.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableScopeImpl.java:68
protected Map<String, VariableInstance> transientVariabes;
protected ELContext cachedElContext;
protected String id;
protected abstract List<VariableInstanceEntity> loadVariableInstances();
protected abstract VariableScopeImpl getParentVariableScope();
protected abstract void initializeVariableInstanceBackPointer(VariableInstanceEntity variableInstance);
protected void ensureVariableInstancesInitialized() {
if (variableInstances == null) {
variableInstances = new HashMap<>();
CommandContext commandContext = Context.getCommandContext();
if (commandContext == null) {
throw new ActivitiException("lazy loading outside command context");
}
List<VariableInstanceEntity> variableInstancesList = loadVariableInstances();
for (VariableInstanceEntity variableInstance : variableInstancesList) {
variableInstances.put(variableInstance.getName(), variableInstance);
}
}
}
@Override
public Map<String, Object> getVariables() {
return collectVariables(new HashMap<>());
}
@Override
public Map<String, VariableInstance> getVariableInstances() {
return collectVariableInstances(new HashMap<>());
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Access variables through the public services (runtimeService.getVariable / taskService.getVariable) which run inside commands
- Wrap custom logic in managementService.executeCommand(...) to establish a CommandContext
- Do not cache or serialize variable-scope entities; re-fetch them per command
- In async code, pass ids/primitive values instead of entity references
Example fix
// before
Object v = detachedExecution.getVariable("status"); // throws
// after
Object v = runtimeService.getVariable(executionId, "status"); Defensive patterns
Strategy: type-guard
Validate before calling
boolean safe = org.activiti.engine.impl.context.Context.getCommandContext() != null;
Type guard
boolean variableAccessAllowed() {
return org.activiti.engine.impl.context.Context.getCommandContext() != null;
} Try / catch
try {
Object v = execution.getVariable("k");
} catch (ActivitiException e) {
if (e.getMessage().contains("lazy loading outside command context")) {
v = runtimeService.getVariable(executionId, "k");
}
} Prevention
- Always read variables via RuntimeService/TaskService
- Wrap custom engine-internal code in executeCommand
- Never pass execution/task entities to async threads — pass ids
When it happens
Trigger: Any variable access (getVariable(s), getVariableNames, setVariable, hasVariable) on an ExecutionEntity/TaskEntity when Context.getCommandContext() is null — outside a command: application threads, async jobs started manually, cached detached entities, code between commands.
Common situations: Reading process/task variables from a Spring service method invoked outside the engine's command chain with a detached entity; using entities in CompletableFuture/executor threads; custom event listeners invoked without the command interceptor; tests instantiating entities directly.
Related errors
- lazy loading outside command context
- lazy loading outside command context for " + this
- Cannot work with cached variables in an active command.
- Cannot initialize byte array. There is no command context an
- lazy loading outside command context for
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/264ca3ac1b69f7e4.
Report an issue: GitHub.