flowable/flowable-engine · error · FlowableException
variable '" + variableName + "' already exists. Use…
Error message
variable '" + variableName + "' already exists. Use setVariableLocal if you want to overwrite the value for " + this
What it means
ExecutionEntityImpl.createVariableLocal refuses to overwrite an existing variable when creating a local variable: if variableInstances already contains the name it throws this FlowableException, directing the caller to setVariableLocal for overwriting. It guards against silently replacing variable values.
Solutions
- Use setVariableLocal(variableName, value) instead of createVariableLocal when overwriting an existing value is intended.
- Guard with a containsKey/hasVariableLocal check and only create when absent, otherwise update.
- Uniquify the variable name per activity instance/loop iteration so re-entry doesn't collide.
Example fix
// before
execution.createVariableLocal("retryCount", 0); // throws on retry pass
// after
if (!execution.hasVariableLocal("retryCount")) {
execution.createVariableLocal("retryCount", 0);
} else {
execution.setVariableLocal("retryCount", 0);
} Defensive patterns
Strategy: validation
Validate before calling
// Java: check existence before creating local variable
if (execution.hasVariableLocal(variableName)) {
execution.setVariableLocal(variableName, value);
} else {
execution.createVariableLocal(variableName, value);
} Type guard
boolean canCreateLocal(VariableScope scope, String name) {
return !scope.hasVariableLocal(name);
} Try / catch
try {
execution.createVariableLocal(name, value);
} catch (FlowableException e) {
if (e.getMessage().contains("already exists")) {
execution.setVariableLocal(name, value);
} else { throw e; }
} Prevention
- Default to setVariableLocal unless you specifically need create-once semantics.
- Make delegates/listeners idempotent for retries and loop iterations.
- Uniquify variable names per activity/loop when multiple branches write.
- Check hasVariableLocal before any create call.
When it happens
Trigger: Calling createVariableLocal (directly or via APIs that create local variables, e.g. executionEntity.createVariableLocal(name, value), DelegateExecution variable creation in JavaDelegates/ExecutionListeners) with a variable name that already exists locally on that execution.
Common situations: Delegate/listener code that initializes a local variable on re-entry or retry (looped subprocess, boundary-event re-execution) where the variable was set in a previous pass; parallel branches each attempting to create the same local name; double-invocation of initialization code.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- variable '
- Ad-hoc sub process has running child executions that need…
- Cannot execute operation because process definition '" +…
- Cannot execute operation: task is suspended
- Cannot execution operation because execution '" +…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/7130778ff4ed82b7.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/ExecutionEntityImpl.java:894
variableListenerSession.addVariableData(variableInstance.getName(), VariableListenerSessionData.VARIABLE_CREATE,
variableInstance.getProcessInstanceId(), ScopeTypes.BPMN, variableInstance.getProcessDefinitionId());
Clock clock = CommandContextUtil.getProcessEngineConfiguration().getClock();
// Record historic variable
CommandContextUtil.getHistoryManager().recordVariableCreate(variableInstance, clock.getCurrentTime());
// Record historic detail
CommandContextUtil.getHistoryManager().recordHistoricDetailVariableCreate(variableInstance, sourceExecution, true,
getRelatedActivityInstanceId(sourceExecution), clock.getCurrentTime());
return variableInstance;
}
protected void createVariableLocal(String variableName, Object value, ExecutionEntity sourceActivityExecution) {
ensureVariableInstancesInitialized();
if (variableInstances.containsKey(variableName)) {
throw new FlowableException("variable '" + variableName + "' already exists. Use setVariableLocal if you want to overwrite the value for " + this);
}
createVariableInstance(variableName, value, sourceActivityExecution);
}
@Override
protected void updateVariableInstance(VariableInstanceEntity variableInstance, Object value) {
updateVariableInstance(variableInstance, value, this);
}
protected void updateVariableInstance(VariableInstanceEntity variableInstance, Object value, ExecutionEntity sourceExecution) {
super.updateVariableInstance(variableInstance, value);
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
VariableListenerSession variableListenerSession = Context.getCommandContext().getSession(VariableListenerSession.class);
variableListenerSession.addVariableData(variableInstance.getName(), VariableListenerSessionData.VARIABLE_UPDATE,
variableInstance.getProcessInstanceId(), ScopeTypes.BPMN, variableInstance.getProcessDefinitionId());
View on GitHub (pinned to d6d39ce1c6)