flowable/flowable-engine · error · FlowableException
Variable ' ' is already present on task ' '.
Error message
Variable '${name}' is already present on task '${task.getId()}'. What it means
REST create/update conflict in TaskVariableBaseResource.setVariable: a variable with the same name already exists on the task while a create operation was requested, so the existing variable must be updated instead.
Solutions
- Use PUT /runtime/tasks/{taskId}/variables/{variableName} to update the existing variable instead of POST
- Delete the variable first (DELETE endpoint) if you need to recreate it
- Check existing variables with GET /runtime/tasks/{taskId}/variables before creating
Defensive patterns
Strategy: validation
Validate before calling
const existing = await api.get(`/runtime/tasks/${taskId}/variables`); if (existing.data.some(v => v.name === name && v.variableScope === scope)) { /* update via PUT instead */ } Try / catch
try { await api.post(`/runtime/tasks/${taskId}/variables`, body); } catch (e) { if (e.response && e.response.status === 409) { await api.put(`/runtime/tasks/${taskId}/variables/${name}`, body); } else { throw e; } } Prevention
- GET existing variables before POST
- Remember POST=create, PUT=update semantics
- Handle concurrent creators with a unique-name discipline
When it happens
Trigger: POST /runtime/tasks/{taskId}/variables with a body whose variable name already exists in the task's local (or chosen) scope. In setVariable(), isNew=true and hasVariableOnScope(task, name, scope) returns true.
Common situations: Re-running a script that creates variables; concurrent requests creating the same variable; confusing POST (create) with PUT (update) semantics; the variable exists locally while the client assumed global scope or vice versa.
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
- A group with id '' already exists.
- Engine property already exists
- User '' is already part of group ''.
- Process definition with id '" + processDefinition.getId() +…
- Process instance with id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/7d6f0d27856f8334.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskVariableBaseResource.java:225
// Figure out scope, revert to local is omitted
RestVariableScope scope = restVariable.getVariableScope();
if (scope == null) {
scope = RestVariableScope.LOCAL;
}
Object actualVariableValue = restResponseFactory.getVariableValue(restVariable);
setVariable(task, restVariable.getName(), actualVariableValue, scope, isNew);
return getVariableFromRequestWithoutAccessCheck(task, restVariable.getName(), scope.name(), false);
}
protected void setVariable(Task task, String name, Object value, RestVariableScope scope, boolean isNew) {
// Create can only be done on new variables. Existing variables should
// be updated using PUT
boolean hasVariable = hasVariableOnScope(task, name, scope);
if (isNew && hasVariable) {
throw new FlowableException("Variable '" + name + "' is already present on task '" + task.getId() + "'.");
}
if (!isNew && !hasVariable) {
throw new FlowableObjectNotFoundException("Task '" + task.getId() + "' does not have a variable with name: '" + name + "'.", null);
}
if (restApiInterceptor != null) {
if (isNew) {
restApiInterceptor.createTaskVariables(task, Collections.singletonMap(name, value), scope);
} else {
restApiInterceptor.updateTaskVariables(task, Collections.singletonMap(name, value), scope);
}
}
if (scope == RestVariableScope.LOCAL) {
taskService.setVariableLocal(task.getId(), name, value);
} else {
if (task.getExecutionId() != null) {View on GitHub (pinned to d6d39ce1c6)