flowable/flowable-engine · error · ActivitiException

variable ' ' already exists. Use setVariableLocal if you…

Error message

variable '${variableName}' already exists. Use setVariableLocal if you want to overwrite the value

What it means

VariableScopeImpl.createVariableLocal is only invoked when a brand-new local variable is created on the scope; it asserts the variable name does not already exist and otherwise throws this ActivitiException. It is an internal invariant guard for setVariableLocal's create path — callers should use setVariableLocal which overwrites, or check existence first. Hitting it means a race or stale scope allowed a duplicate creation attempt.

Solutions

  1. Use setVariableLocal (or setVariable) which overwrites existing values instead of the create-only path
  2. Guard creation with a check: hasVariableLocal(name) before creating, or just always assign
  3. Serialize updates to the same execution (avoid parallel writes to one variable) or rely on optimistic locking and retry the command
  4. Rename variables per branch (e.g. prefix with branch id) to avoid cross-scope collisions

Example fix

// before
task.setVariableLocal("approval", value); // may hit duplicate create under concurrency
// after
if (!task.hasVariableLocal("approval")) {
    task.setVariableLocal("approval", value);
} else {
    task.setVariableLocal("approval", value); // overwrite path
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean exists = scope.hasVariableLocal(variableName);

Try / catch

try {
    createVariableLocal(name, value, sourceExecution);
} catch (ActivitiException e) {
    if (e.getMessage().contains("already exists")) {
        scope.setVariableLocal(name, value); // overwrite instead
    }
}

Prevention

When it happens

Trigger: Creating a local variable on an execution/task whose variableInstances map already contains that name — e.g. concurrent setVariableLocal calls from two threads/transactions, or an internal create path invoked when initialization revealed the variable already present.

Common situations: Parallel branches or multiple service tasks setting the same local variable name simultaneously; retrying a failed transaction whose first attempt partially created the variable; custom code mixing setVariable and setVariableLocal on the same name; two engine nodes racing on the same execution without optimistic-lock handling.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/8f7b2690dd194581. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableScopeImpl.java:822

            }

            return null;

        }
    }

    public void createVariableLocal(String variableName, Object value) {
        createVariableLocal(variableName, value, getSourceActivityExecution());
    }

    /**
     * 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, ExecutionEntity sourceActivityExecution) {
        ensureVariableInstancesInitialized();

        if (variableInstances.containsKey(variableName)) {
            throw new ActivitiException("variable '" + variableName + "' already exists. Use setVariableLocal if you want to overwrite the value");
        }

        createVariableInstance(variableName, value, sourceActivityExecution);
    }

    @Override
    public void removeVariable(String variableName) {
        removeVariable(variableName, getSourceActivityExecution());
    }

    protected void removeVariable(String variableName, ExecutionEntity sourceActivityExecution) {
        ensureVariableInstancesInitialized();
        if (variableInstances.containsKey(variableName)) {
            removeVariableLocal(variableName);
            return;
        }
        VariableScopeImpl parentVariableScope = getParentVariableScope();
        if (parentVariableScope != null) {

View on GitHub (pinned to d6d39ce1c6)