flowable/flowable-engine · error · FlowableException
variable '
Error message
variable '
What it means
createVariableLocal enforces that a newly created local variable does not already exist in this scope. If variableInstances already contains the given name, it throws FlowableException "variable '<name>' already exists. Use setVariableLocal if you want to overwrite the value".
Solutions
- Use setVariableLocal(name, value) (or setVariable) to create-or-overwrite instead of createVariableLocal
- Check hasVariableLocal(name)/getVariableInstanceLocal(name) before creating
- On retry/re-execution paths, upsert the variable rather than create it
Example fix
// before
execution.createVariableLocal("status", "new");
// after
execution.setVariableLocal("status", "new"); Defensive patterns
Strategy: validation
Validate before calling
if (scope.hasVariableLocal(variableName)) {
scope.setVariableLocal(variableName, value);
} else {
scope.setVariableLocal(variableName, value); // set handles both create and overwrite
} Try / catch
try {
execution.createVariableLocal(name, value);
} catch (org.flowable.common.engine.api.FlowableException e) {
if (e.getMessage().startsWith("variable '" + name + "' already exists")) {
execution.setVariableLocal(name, value);
} else {
throw e;
}
} Prevention
- Prefer setVariableLocal/setVariable (create-or-overwrite) over low-level create APIs
- Check hasVariableLocal before creating a variable
- Make retry paths idempotent with upsert semantics
When it happens
Trigger: Calling createVariableLocal (directly or via internal APIs) for a variable name that already exists locally on the scope, e.g. re-creating a variable during delegate execution or in listener code instead of updating it.
Common situations: Custom delegates calling low-level create APIs; process re-execution after a retry where the variable already persisted; code that should use setVariable/setVariableLocal but calls create.
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
- couldn't find a variable type that is able to serialize
- variable '" + variableName + "' already exists. Use…
- variableName is null
- A process instance id is required, but the provided id '" +…
- A process instance id is required, but the provided id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/853def2feaf1e2a8.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/persistence/entity/VariableScopeImpl.java:794
} else {
variable = createVariableInstance(variableName, value);
}
usedVariablesCache.put(variableName, variable);
}
}
return null;
}
/**
* only called when a new variable is created on this variable scope. This method is also responsible for propagating the creation of this variable to the history.
*/
protected void createVariableLocal(String variableName, Object value) {
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);
}
@Override
public void removeVariable(String variableName) {
ensureVariableInstancesInitialized();
if (variableInstances.containsKey(variableName)) {
removeVariableLocal(variableName);
return;
}
VariableScopeImpl parentVariableScope = getParentVariableScope();
if (parentVariableScope != null) {
parentVariableScope.removeVariable(variableName);
}
}
View on GitHub (pinned to d6d39ce1c6)