flowable/flowable-engine · error · FlowableIllegalArgumentException
Only allowed to update multiple variables in the same scope.
Error message
Only allowed to update multiple variables in the same scope.
What it means
FlowableIllegalArgumentException thrown by createTaskVariable when the batch of variables in one request mixes scopes (e.g. some LOCAL, some GLOBAL/CASE). The collection endpoint applies one shared scope to all variables in the request, so all entries must agree. Mixed-scope batches are rejected up-front to avoid partial writes.
Solutions
- Set the same variableScope value on every variable in the request body
- Omit variableScope on all entries so all default to LOCAL
- Split the batch into separate requests, one per scope
- Set individual variables through the single-variable endpoint with its own scope
Example fix
// before
[{ "name": "a", "value": 1, "variableScope": "local" }, { "name": "b", "value": 2, "variableScope": "global" }]
// after
[{ "name": "a", "value": 1, "variableScope": "local" }, { "name": "b", "value": 2, "variableScope": "local" }] Defensive patterns
Strategy: validation
Validate before calling
const scopes = new Set(variables.map(v => v.variableScope ?? 'local'));
if (scopes.size > 1) throw new Error('All variables in one request must share the same scope'); Try / catch
try { await api.post(`/tasks/${taskId}/variables`, body); }
catch (e) { if (/same scope/i.test(e.message)) splitByScopeAndRetry(); else throw e; } Prevention
- Normalize variableScope across the batch before sending
- Omit scope entirely to default all to LOCAL
- Group variables by scope and issue one request per scope
When it happens
Trigger: POST /cmmn-runtime/tasks/{taskId}/variables with a body where one entry has variableScope "local" and another has "global" (or "case"), so varScope != sharedScope during iteration.
Common situations: Bulk-setting variables copied from a mixed-scope map; clients that default one variable's scope field differently from the rest; templates that inject a scope into some entries only.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Cannot set global variable '
- Cannot set global variables on task
- Invalid variable scope
- Local variable ' ' is already present on plan item instance…
- Process definition with id '" + processDefinition.getId() +…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/a2b5c86407c316c2.
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:171
RestVariableScope sharedScope = null;
RestVariableScope varScope = null;
Map<String, Object> variablesToSet = new HashMap<>();
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);View on GitHub (pinned to d6d39ce1c6)