flowable/flowable-engine · error · FlowableConflictException

Variable ' ' is already present on task ' '.

Error message

Variable '${name}' is already present on task '${taskId}'.

What it means

FlowableConflictException thrown by createTaskVariable when a variable with the same name already exists on the task in the target scope. The collection-create endpoint only adds new variables; it refuses to silently overwrite existing ones. The client must delete the variable first or use the update (PUT) endpoint.

Solutions

  1. Use PUT /cmmn-runtime/tasks/{taskId}/variables/{name} to overwrite an existing variable
  2. DELETE the existing variable before POSTing it again
  3. Skip names already present (query GET /variables first)
  4. Use a different variable name if a new variable is intended

Example fix

// before
POST /cmmn-runtime/tasks/123/variables  [{"name":"status","value":"done"}]
// after
PUT /cmmn-runtime/tasks/123/variables/status  {"name":"status","value":"done"}
Defensive patterns

Strategy: validation

Validate before calling

const existing = (await api.get(`/tasks/${taskId}/variables`)).data.map(v => v.name);
const dupes = variables.filter(v => existing.includes(v.name));
if (dupes.length) throw new Error(`Variables already present: ${dupes.map(d => d.name).join(', ')}`);

Try / catch

try { await api.post(`/tasks/${taskId}/variables`, body); }
catch (e) { if (e.status === 409) await putUpdateInstead(body); else throw e; }

Prevention

When it happens

Trigger: POST /cmmn-runtime/tasks/{taskId}/variables with a body containing a variable whose name is already set on the task in the same scope, as checked by hasVariableOnScope.

Common situations: Replaying a create request after a partial failure; scripts that add variables on retry; clients that should be calling PUT /variables/{variableName} instead of POST.

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/94d89ab88a7ad0a8. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskVariableCollectionResource.java:175

            for (RestVariable var : inputVariables) {
                // Validate if scopes match
                varScope = var.getVariableScope();
                if (var.getName() == null) {
                    throw new FlowableIllegalArgumentException("Variable name is required");
                }

                if (varScope == null) {
                    varScope = RestVariableScope.LOCAL;
                }
                if (sharedScope == null) {
                    sharedScope = varScope;
                }
                if (varScope != sharedScope) {
                    throw new FlowableIllegalArgumentException("Only allowed to update multiple variables in the same scope.");
                }

                if (hasVariableOnScope(task, var.getName(), varScope)) {
                    throw new FlowableConflictException("Variable '" + var.getName() + "' is already present on task '" + task.getId() + "'.");
                }

                Object actualVariableValue = restResponseFactory.getVariableValue(var);
                variablesToSet.put(var.getName(), actualVariableValue);
            }

            if (!variablesToSet.isEmpty()) {
                if (restApiInterceptor != null) {
                    restApiInterceptor.createTaskVariables(task, variablesToSet, sharedScope);
                }

                Map<String, Object> setVariables;
                if (sharedScope == RestVariableScope.LOCAL) {
                    taskService.setVariablesLocal(task.getId(), variablesToSet);
                    setVariables = taskService.getVariablesLocal(task.getId(), variablesToSet.keySet());
                } else {
                    if (task.getScopeId() != null) {
                        // Explicitly set on case, setting non-local

View on GitHub (pinned to d6d39ce1c6)