flowable/flowable-engine · error · FlowableConflictException
Variable ' ' is already present on execution ' '.
Error message
Variable '${name}' is already present on execution '${executionId}'. What it means
FlowableConflictException thrown when creating/updating variables on an execution without the 'override' flag while a variable with the same name already exists on that scope. The REST API refuses to silently overwrite an existing variable; callers must explicitly set override=true or use a different name.
Solutions
- Set the override query parameter to true on the request (e.g. POST .../variables?override=true) so existing variables are replaced.
- Remove or rename the duplicate variable from the request body.
- Before sending, GET the existing variables and only include ones not already present, or merge values client-side.
- Catch FlowableConflictException (HTTP 409) and decide per-variable whether to overwrite in a follow-up override call.
Example fix
// before
POST /runtime/process-instances/{id}/variables
[{"name":"orderId","value":"42"}]
// after
POST /runtime/process-instances/{id}/variables?override=true
[{"name":"orderId","value":"42"}] Defensive patterns
Strategy: validation
Validate before calling
const existing = await fetch(`/runtime/process-instances/${pid}/variables`).then(r => r.json());
const existingNames = new Set(existing.map(v => v.name));
const dupes = body.variables.filter(v => existingNames.has(v.name));
if (dupes.length && !override) throw new Error(`Variables already present: ${dupes.map(d => d.name).join(',')}`); Try / catch
try { /* setVariables call */ } catch (e) {
if (e.status === 409 || /is already present on execution/.test(e.message)) {
// re-issue with override=true or merge values
} else throw e;
} Prevention
- Pass override=true whenever idempotent overwrite semantics are intended
- GET existing variables first and diff against your payload
- Use stable, unique variable names per integration to avoid collisions
- Handle HTTP 409 explicitly in retry logic instead of blind retries
When it happens
Trigger: POST/PUT to /runtime/process-instances/{id}/variables or /runtime/executions/{id}/variables with override=false (or absent) and a body containing a variable whose name already exists on the execution's scope.
Common situations: Re-submitting a variable-set request after a partial failure; a workflow engine or script that re-sets process variables on retry; two integrations writing the same variable name; client assumes PUT semantics (idempotent overwrite) but default override is false.
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
- Cannot set global variables on execution
- Execution ' ' does not have a variable ' ' in scope
- Failed to serialize to a RestVariable instance
- Historic process instance '" + processInstanceId + "'…
- Invalid body was supplied
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/7b52fa33518e77c5.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/BaseVariableCollectionResource.java:130
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 (!override && hasVariableOnScope(execution, var.getName(), varScope)) {
throw new FlowableConflictException("Variable '" + var.getName() + "' is already present on execution '" + execution.getId() + "'.");
}
Object actualVariableValue = restResponseFactory.getVariableValue(var);
variablesToSet.put(var.getName(), actualVariableValue);
}
if (!variablesToSet.isEmpty()) {
if (restApiInterceptor != null) {
restApiInterceptor.createExecutionVariables(execution, variablesToSet, sharedScope);
}
Map<String, Object> setVariables = null;
if (sharedScope == RestVariableScope.LOCAL) {
if (async) {
runtimeService.setVariablesLocalAsync(execution.getId(), variablesToSet);
} else {View on GitHub (pinned to d6d39ce1c6)