flowable/flowable-engine · error · FlowableException

Variable '" + name + "' is already present on execution '"…

Error message

Variable '" + name + "' is already present on execution '" + execution.getId() + "'.

What it means

FlowableException thrown in setVariable when creating a variable (isNew=true) that already exists on the execution for the given scope. Creation is reserved for new variables; existing variables must be updated via PUT.

Solutions

  1. Use PUT /runtime/executions/{id}/variables/{name} to update an existing variable instead of POST
  2. Check existence first with GET on the variable, or use the upsert semantics of PUT variables collection where supported
  3. Handle duplicate creation in client code with idempotency (update if exists)

Example fix

// before
POST /runtime/executions/123/variables  {"name":"status","value":"new"}  // 2nd time -> error
// after
PUT /runtime/executions/123/variables/status  {"value":"new"}
Defensive patterns

Strategy: validation

Validate before calling

ResponseEntity<String> existing = rest.getForEntity(base + "/runtime/executions/" + id + "/variables/" + name, String.class);
boolean isNew = existing.getStatusCode() == HttpStatus.NOT_FOUND;

Type guard

null

Try / catch

try { client.createExecutionVariable(id, var); } catch (HttpClientErrorException e) { if (e.getRawStatusCode() == 409 || e.getResponseBodyAsString().contains("already present")) { client.updateExecutionVariable(id, var.getName(), var); } }

Prevention

When it happens

Trigger: POST /runtime/executions/{executionId}/variables with a variable whose name+scope already exists on that execution.

Common situations: Re-running a client that POSTs the same variable set without checking existence; using POST instead of PUT for an update; race between two requests creating the same variable.

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/05e7c05f30094881. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/BaseExecutionVariableResource.java:219

        }

        Object actualVariableValue = restResponseFactory.getVariableValue(restVariable);
        setVariable(execution, restVariable.getName(), actualVariableValue, scope, isNew, async);

        RestVariable newRestVariable = null;
        if (!async) {
            newRestVariable = getVariableFromRequestWithoutAccessCheck(execution, restVariable.getName(), scope, false);
        }
        
        return newRestVariable;
    }

    protected void setVariable(Execution execution, String name, Object value, RestVariableScope scope, boolean isNew, boolean async) {
        // Create can only be done on new variables. Existing variables should
        // be updated using PUT
        boolean hasVariable = hasVariableOnScope(execution, name, scope);
        if (isNew && hasVariable) {
            throw new FlowableException("Variable '" + name + "' is already present on execution '" + execution.getId() + "'.");
        }

        if (!isNew && !hasVariable) {
            throw new FlowableObjectNotFoundException("Execution '" + execution.getId() + "' does not have a variable with name: '" + name + "'.", null);
        }

        if (restApiInterceptor != null) {
            if (isNew) {
                restApiInterceptor.createExecutionVariables(execution, Collections.singletonMap(name, value), scope);
            } else {
                restApiInterceptor.updateExecutionVariables(execution, Collections.singletonMap(name, value), scope);
            }
        }

        if (scope == RestVariableScope.LOCAL) {
            if (async) {
                runtimeService.setVariableLocalAsync(execution.getId(), name, value);
            } else {

View on GitHub (pinned to d6d39ce1c6)