{"record":{"id":"baf2c19329c73ad0","repo":"flowable/flowable-engine","slug":"not-allowed-to-set-variables-in-a-bpmn-error-varia","errorCode":null,"errorMessage":"Not allowed to set variables in a bpmn error variable container","messagePattern":"Not allowed to set variables in a bpmn error variable container","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ErrorPropagation.java","lineNumber":648,"sourceCode":"\n        @Override\n        public Object getVariable(String variableName) {\n            if (ERROR_CODE_VARIABLE_NAME.equals(variableName)) {\n                return errorCode;\n            } else if (ERROR_VARIABLE_NAME.equals(variableName)) {\n                return error;\n            } else if (ERROR_MESSAGE_VARIABLE_NAME.equals(variableName)) {\n                return error != null ? error.getMessage() : null;\n            } else if (additionalDataContainer != null) {\n                return additionalDataContainer.getVariable(variableName);\n            }\n\n            return null;\n        }\n\n        @Override\n        public void setVariable(String variableName, Object variableValue) {\n            throw new UnsupportedOperationException(\"Not allowed to set variables in a bpmn error variable container\");\n        }\n\n        @Override\n        public void setTransientVariable(String variableName, Object variableValue) {\n            throw new UnsupportedOperationException(\"Not allowed to set variables in a bpmn error variable container\");\n        }\n\n        @Override\n        public String getTenantId() {\n            return tenantId;\n        }\n\n        @Override\n        public Set<String> getVariableNames() {\n            if (additionalDataContainer == null) {\n                return Set.of(ERROR_CODE_VARIABLE_NAME, ERROR_VARIABLE_NAME, ERROR_MESSAGE_VARIABLE_NAME);\n            }\n","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ErrorPropagation.java#L630-L666","documentation":"Thrown as UnsupportedOperationException by the anonymous BpmnErrorVariableContainer in ErrorPropagation.setVariable. The error variable container passed to BpmnError handling is read-only; Flowable forbids writing variables into it, so any setVariable call fails unconditionally.","triggerScenarios":"Code holding the BpmnErrorVariableContainer built during error propagation (e.g. inside an event handler / error variable mapping that receives this container as a VariableScope) calls setVariable(name, value).","commonSituations":"Custom error/variable mapping code or listeners that attempt to persist variables while handling a caught BpmnError; reused generic variable-writing helper invoked in the error context; assuming the container behaves like an ExecutionEntity.","solutions":["Write variables on the DelegateExecution / process execution instead of the error variable container","Read-only usage: only call getter methods (getVariable, getTenantId) on this container","Capture values into the error event's variable mappings defined in the BPMN (in/out mappings) rather than calling setVariable","Guard custom code with an instanceof/capability check before writing variables"],"exampleFix":"// before\nerrorVariableContainer.setVariable(\"reason\", msg);\n// after\n((DelegateExecution) execution).setVariable(\"reason\", msg);","handlingStrategy":"try-catch","validationCode":"if (scope instanceof DelegateExecution) {\n    ((DelegateExecution) scope).setVariable(name, value);\n} else {\n    throw new IllegalStateException(\"Refusing to write variables on read-only scope: \" + scope.getClass());\n}","typeGuard":"static boolean isWritableVariableScope(VariableScope scope) {\n    return !(scope instanceof DelegateExecution) || scope instanceof ExecutionEntity;\n}","tryCatchPattern":"try { scope.setVariable(name, value); }\ncatch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"bpmn error variable container\")) {\n        log.warn(\"Container is read-only; write to execution instead\");\n    } else throw e;\n}","preventionTips":["Never treat BpmnErrorVariableContainer as writable; it is a read-only view","Move variable writes into BPMN in/out mappings or the parent execution","Review generic variable-copy utilities for scope-blind writes"],"tags":["java","unsupported-operation","bpmnerror","variables"],"backgroundTag":"unsupported-operation","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"}