{"record":{"id":"47469cdfcb5fdc83","repo":"flowable/flowable-engine","slug":"empty-object-no-variables-can-be-set-47469c","errorCode":null,"errorMessage":"Empty object, no variables can be set","messagePattern":"Empty object, no variables can be set","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"modules/flowable-variable-service-api/src/main/java/org/flowable/variable/api/delegate/EmptyVariableScope.java","lineNumber":152,"sourceCode":"\n    @Override\n    public VariableInstance getVariableInstance(String variableName, boolean fetchAllVariables) {\n        return null;\n    }\n\n    @Override\n    public VariableInstance getVariableInstanceLocal(String variableName) {\n        return null;\n    }\n\n    @Override\n    public VariableInstance getVariableInstanceLocal(String variableName, boolean fetchAllVariables) {\n        return null;\n    }\n\n    @Override\n    public void setVariable(String variableName, Object value) {\n        throw new UnsupportedOperationException(\"Empty object, no variables can be set\");\n    }\n\n    @Override\n    public void setVariable(String variableName, Object value, boolean fetchAllVariables) {\n        throw new UnsupportedOperationException(\"Empty object, no variables can be set\");\n    }\n\n    @Override\n    public Object setVariableLocal(String variableName, Object value) {\n        throw new UnsupportedOperationException(\"Empty object, no variables can be set\");\n    }\n\n    @Override\n    public Object setVariableLocal(String variableName, Object value, boolean fetchAllVariables) {\n        throw new UnsupportedOperationException(\"Empty object, no variables can be set\");\n    }\n\n    @Override","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-variable-service-api/src/main/java/org/flowable/variable/api/delegate/EmptyVariableScope.java#L134-L170","documentation":"EmptyVariableScope is an immutable no-op VariableScope placeholder (e.g. used for executions/tasks that no longer exist or as a null-scope stand-in in delegate expression evaluation). Every mutating method deliberately throws UnsupportedOperationException because an empty scope can never hold variables. Throwing here is the library's contract that mutation on this object is a programming error.","triggerScenarios":"Calling setVariable(String, Object) on an EmptyVariableScope instance, typically obtained when the delegate/execution resolves to the EMPTY sentinel scope instead of a real ExecutionEntity/TaskEntity.","commonSituations":"Delegate code (JavaDelegate/TaskListener) calling execution.setVariable(...) when the execution was replaced by EmptyVariableScope (e.g. after process instance end or in history/simulation contexts); passing EmptyVariableScope into helper code expecting a writable scope.","solutions":["Verify the scope you hold is a real, still-active execution/task before mutating: check the scope type or re-fetch the execution via runtimeService.","Move variable writes earlier in the lifecycle (before process instance end / completion) inside the actual delegate execution.","Guard mutation with an instanceof/type check for EmptyVariableScope and skip or log instead of mutating.","If you intentionally need a throwaway scope, use a custom VariableScope implementation instead of the empty sentinel."],"exampleFix":"// before\nscope.setVariable(\"status\", \"done\");\n\n// after\nif (scope instanceof EmptyVariableScope) {\n    logger.warn(\"Skipping variable write: scope is empty/detached\");\n} else {\n    scope.setVariable(\"status\", \"done\");\n}","handlingStrategy":"type-guard","validationCode":"if (scope == null || scope instanceof EmptyVariableScope) {\n    throw new IllegalStateException(\"Scope is not writable\");\n}","typeGuard":"boolean isWritableScope(VariableScope scope) {\n    return scope != null && !(scope instanceof EmptyVariableScope);\n}","tryCatchPattern":"try {\n    scope.setVariable(\"status\", value);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Empty object\")) {\n        logger.warn(\"Variable write skipped: scope is empty/detached\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always mutate variables via the live VariableScope injected into delegates/listeners, never via cached references.","Avoid writes after the process instance or task has completed.","Add an EmptyVariableScope check at helper/utility boundaries that accept VariableScope.","Fetch scopes fresh from runtimeService/taskService when in doubt."],"tags":["flowable","unsupported-operation","variable-scope","immutable"],"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"}