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

REST request validation in TaskVariableCollectionResource.createTaskVariable: the submitted variable list mixes LOCAL and GLOBAL scopes; a single bulk create is only allowed when all variables share one scope.

Solutions

  1. Make all entries use the same "variableScope" in one request
  2. Split the payload into two requests: one for local, one for global
  3. Omit "variableScope" everywhere to use the default (local)

Example fix

// before
[{"name":"a","value":1,"variableScope":"local"},{"name":"b","value":2,"variableScope":"global"}]
// after (two requests)
POST /variables [{"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('Split into per-scope requests: ' + [...scopes]); }

Type guard

function sameScope(vars) { return new Set(vars.map(v => v.variableScope || 'local')).size <= 1; }

Try / catch

try { await api.post(`/runtime/tasks/${taskId}/variables`, vars); } catch (e) { if (e.response && e.response.status === 400 && /same scope/.test(e.response.data.message || '')) { await Promise.all(groupByScope(vars).map(g => api.post(`/runtime/tasks/${taskId}/variables`, g))); } else { throw e; } }

Prevention

When it happens

Trigger: POST /runtime/tasks/{taskId}/variables with [{"name":"a","variableScope":"local"},{"name":"b","variableScope":"global"}] (or one entry omitting scope, which defaults to local, alongside an explicit global).

Common situations: Bulk payloads assembled from mixed sources; forgetting the default-to-local behavior so an unscoped entry conflicts with an explicit global; splitting one variables map into scopes without grouping first.

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

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskVariableCollectionResource.java:170

            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)