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

  1. Set the same variableScope value on every variable in the request body
  2. Omit variableScope on all entries so all default to LOCAL
  3. Split the batch into separate requests, one per scope
  4. 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

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


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)