flowable/flowable-engine · error · FlowableConflictException
Local variable ' ' is already present on plan item instance…
Error message
Local variable '${name}' is already present on plan item instance '${instanceId}'. What it means
When creating a LOCAL variable via the CMMN REST API with the 'new variable' semantics (isNew) and async flag path, Flowable first checks runtimeService.hasLocalVariable; if a local variable with that name already exists on the plan item instance, it throws FlowableConflictException (HTTP 409) instead of silently overwriting. This protects callers from accidentally clobbering existing local variables.
Solutions
- Use PUT (update) on the existing variable instead of POST create if overwriting is intended
- Check existence first via GET /cmmn-runtime/plan-item-instances/{id}/variables/{name} and choose POST or PUT accordingly
- Use a different variable name, or remove the existing local variable before recreating
- Treat HTTP 409 as 'already exists' in client retry logic and switch to update
Example fix
// before: always POST
post(variablesUrl, newVariable(name, value, LOCAL));
// after
if (!exists(variablesUrl + "/" + name)) {
post(variablesUrl, newVariable(name, value, LOCAL));
} else {
put(variablesUrl + "/" + name, newVariable(name, value, LOCAL));
} Defensive patterns
Strategy: validation
Validate before calling
boolean exists = restTemplate.getForObject(
base + "/cmmn-runtime/plan-item-instances/" + planItemId + "/variables/" + name, Boolean.class) != null;
if (exists) {
// update via PUT instead of POST create
} Type guard
null
Try / catch
try {
postLocalVariable(planItemId, name, value);
} catch (HttpClientErrorException.Conflict e) {
putLocalVariable(planItemId, name, value); // fall back to update
} Prevention
- Check variable existence before POSTing new local variables
- Use PUT for idempotent updates instead of POST create
- Handle HTTP 409 as 'already exists' in retry logic
- Avoid concurrent creation of the same variable name from multiple clients
When it happens
Trigger: POSTing a new local variable to /cmmn-runtime/plan-item-instances/{id}/variables with scope=local for a variable name that already exists locally on that plan item instance, when isNew is true.
Common situations: Retry logic re-POSTing a variable that was already created in a previous attempt, concurrent clients creating the same variable name, scripts that assume variables are upserted when the create endpoint is actually create-only.
Related errors
- Variable name is required.
- Can only complete BPMN external job with a BPMN error. Job…
- Can only terminate CMMN external job. Job with id
- Cannot complete CMMN job. There is no CMMN engine available
- Cannot delete a task that is part of a case instance.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/74a8bbe28cd84dc3.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/BaseVariableResource.java:403
throw new FlowableIllegalArgumentException("Could not process multipart content", ioe);
} catch (ClassNotFoundException ioe) {
throw new FlowableContentNotSupportedException(
"The provided body contains a serialized object for which the class was not found: " + ioe.getMessage());
}
}
protected void setVariable(String instanceId, String name, Object value, RestVariableScope scope, boolean isNew, boolean async, VariableInterceptor variableInterceptor) {
if (isNew) {
variableInterceptor.createVariables(Collections.singletonMap(name, value));
} else {
variableInterceptor.updateVariables(Collections.singletonMap(name, value));
}
if (RestVariableScope.LOCAL == scope) {
//the guard is only added here, because this whole block is new
if (isNew && runtimeService.hasLocalVariable(instanceId, name)) {
throw new FlowableConflictException("Local variable '" + name + "' is already present on plan item instance '" + instanceId + "'.");
}
if (async) {
runtimeService.setLocalVariableAsync(instanceId, name, value);
} else {
runtimeService.setLocalVariable(instanceId, name, value);
}
} else {
if (async) {
runtimeService.setVariableAsync(instanceId, name, value);
} else {
runtimeService.setVariable(instanceId, name, value);
}
}
}
protected VariableInterceptor createVariableInterceptor(PlanItemInstance planItemInstance) {View on GitHub (pinned to d6d39ce1c6)