{"record":{"id":"971edd4c1a02c7c0","repo":"flowable/flowable-engine","slug":"only-allowed-to-update-multiple-variables-in-the-s-971edd","errorCode":null,"errorMessage":"Only allowed to update multiple variables in the same scope.","messagePattern":"Only allowed to update multiple variables in the same scope\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/BaseVariableCollectionResource.java","lineNumber":126,"sourceCode":"            RestVariableScope sharedScope = null;\n            RestVariableScope varScope = null;\n            Map<String, Object> variablesToSet = new HashMap<>();\n\n            for (RestVariable var : inputVariables) {\n                // Validate if scopes match\n                varScope = var.getVariableScope();\n                if (var.getName() == null) {\n                    throw new FlowableIllegalArgumentException(\"Variable name is required\");\n                }\n\n                if (varScope == null) {\n                    varScope = RestVariableScope.LOCAL;\n                }\n                if (sharedScope == null) {\n                    sharedScope = varScope;\n                }\n                if (varScope != sharedScope) {\n                    throw new FlowableIllegalArgumentException(\"Only allowed to update multiple variables in the same scope.\");\n                }\n\n                if (!override && hasVariableOnScope(execution, var.getName(), varScope)) {\n                    throw new FlowableConflictException(\"Variable '\" + var.getName() + \"' is already present on execution '\" + execution.getId() + \"'.\");\n                }\n\n                Object actualVariableValue = restResponseFactory.getVariableValue(var);\n                variablesToSet.put(var.getName(), actualVariableValue);\n            }\n\n            if (!variablesToSet.isEmpty()) {\n                if (restApiInterceptor != null) {\n                    restApiInterceptor.createExecutionVariables(execution, variablesToSet, sharedScope);\n                }\n\n                Map<String, Object> setVariables = null;\n                if (sharedScope == RestVariableScope.LOCAL) {\n                    ","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/BaseVariableCollectionResource.java#L108-L144","documentation":"All variables in one batch-creation request must target the same scope. createExecutionVariable records the scope of the first variable (defaulting to LOCAL) and throws FlowableIllegalArgumentException as soon as a later variable declares a different scope (GLOBAL vs LOCAL). Mixed-scope batches would make transactional semantics ambiguous, so they are rejected.","triggerScenarios":"POSTing a variables array like [{\"name\":\"a\",\"scope\":\"global\"},{\"name\":\"b\",\"scope\":\"local\"}] to a variables collection endpoint.","commonSituations":"Merging variables from two different contexts into one request; copying an example that used GLOBAL and appending LOCAL variables; generic UIs that let users pick scope per variable but batch-submit all at once.","solutions":["Split the batch into separate requests, one per scope (all GLOBAL in one call, all LOCAL in another)","Set a uniform \"scope\" on every element of the array (or omit it so all default to LOCAL)","Submit scope-specific variables through the dedicated endpoint (e.g. .../variables/{variableName} with scope in the body) instead of batching"],"exampleFix":"// before\n[{\"name\":\"a\",\"scope\":\"global\",\"value\":1},{\"name\":\"b\",\"scope\":\"local\",\"value\":2}]\n// after\n[{\"name\":\"a\",\"scope\":\"global\",\"value\":1},{\"name\":\"b\",\"scope\":\"global\",\"value\":2}]  // second batch with scope \"local\" sent separately","handlingStrategy":"validation","validationCode":"const scopes = new Set(variables.map(v => v.scope || 'local')); if (scopes.size > 1) throw new Error('batch contains mixed scopes: ' + [...scopes].join(','));","typeGuard":"function singleScope(vars) { const s = new Set(vars.map(v => v.scope || 'local')); return s.size <= 1; }","tryCatchPattern":"try { await api.post(url, vars); } catch (e) { if (e.message.includes('same scope')) { for (const scope of ['global','local']) { const batch = vars.filter(v => (v.scope||'local') === scope); if (batch.length) await api.post(url, batch); } } }","preventionTips":["Group variables by scope before batching; issue one request per scope","Omit \"scope\" entirely to accept the LOCAL default uniformly","Enforce a uniform scope in your payload-building layer"],"tags":["flowable","rest-api","variables","scope","batch"],"backgroundTag":"mixed-variable-scopes","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}