{"record":{"id":"8f7b2690dd194581","repo":"flowable/flowable-engine","slug":"variable-variablename-already-exists-use-set","errorCode":null,"errorMessage":"variable '${variableName}' already exists. Use setVariableLocal if you want to overwrite the value","messagePattern":"variable '(.+?)' already exists\\. Use setVariableLocal if you want to overwrite the value","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableScopeImpl.java","lineNumber":822,"sourceCode":"            }\n\n            return null;\n\n        }\n    }\n\n    public void createVariableLocal(String variableName, Object value) {\n        createVariableLocal(variableName, value, getSourceActivityExecution());\n    }\n\n    /**\n     * 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.\n     */\n    protected void createVariableLocal(String variableName, Object value, ExecutionEntity sourceActivityExecution) {\n        ensureVariableInstancesInitialized();\n\n        if (variableInstances.containsKey(variableName)) {\n            throw new ActivitiException(\"variable '\" + variableName + \"' already exists. Use setVariableLocal if you want to overwrite the value\");\n        }\n\n        createVariableInstance(variableName, value, sourceActivityExecution);\n    }\n\n    @Override\n    public void removeVariable(String variableName) {\n        removeVariable(variableName, getSourceActivityExecution());\n    }\n\n    protected void removeVariable(String variableName, ExecutionEntity sourceActivityExecution) {\n        ensureVariableInstancesInitialized();\n        if (variableInstances.containsKey(variableName)) {\n            removeVariableLocal(variableName);\n            return;\n        }\n        VariableScopeImpl parentVariableScope = getParentVariableScope();\n        if (parentVariableScope != null) {","sourceCodeStart":804,"sourceCodeEnd":840,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/VariableScopeImpl.java#L804-L840","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use setVariableLocal (or setVariable) which overwrites existing values instead of the create-only path","Guard creation with a check: hasVariableLocal(name) before creating, or just always assign","Serialize updates to the same execution (avoid parallel writes to one variable) or rely on optimistic locking and retry the command","Rename variables per branch (e.g. prefix with branch id) to avoid cross-scope collisions"],"exampleFix":"// before\ntask.setVariableLocal(\"approval\", value); // may hit duplicate create under concurrency\n// after\nif (!task.hasVariableLocal(\"approval\")) {\n    task.setVariableLocal(\"approval\", value);\n} else {\n    task.setVariableLocal(\"approval\", value); // overwrite path\n}","handlingStrategy":"try-catch","validationCode":"boolean exists = scope.hasVariableLocal(variableName);","typeGuard":null,"tryCatchPattern":"try {\n    createVariableLocal(name, value, sourceExecution);\n} catch (ActivitiException e) {\n    if (e.getMessage().contains(\"already exists\")) {\n        scope.setVariableLocal(name, value); // overwrite instead\n    }\n}","preventionTips":["Prefer setVariableLocal (upsert semantics) over create-only paths","Avoid concurrent writes to the same variable on one execution; retry on optimistic lock","Use distinct variable names per branch/scope","Check hasVariableLocal before creating"],"tags":["variables","concurrency","scope","duplicate"],"backgroundTag":"duplicate-variable-creation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}