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

  1. Use setVariableLocal(name, value) (or setVariable) to create-or-overwrite instead of createVariableLocal
  2. Check hasVariableLocal(name)/getVariableInstanceLocal(name) before creating
  3. 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

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


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)