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

  1. Use setVariableLocal(variableName, value) instead of createVariableLocal when overwriting an existing value is intended.
  2. Guard with a containsKey/hasVariableLocal check and only create when absent, otherwise update.
  3. 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

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


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)