flowable/flowable-engine · error · UnsupportedOperationException
Empty object, no variables can be created
Error message
Empty object, no variables can be created
What it means
EmptyVariableScope.createVariableLocal(String, Object) always throws UnsupportedOperationException. Unlike the setVariable family, createVariableLocal creates the variable immediately rather than deferring, which is impossible on the immutable empty scope.
Solutions
- Check for EmptyVariableScope before creating and fetch the live task/execution via its id.
- Create local variables while the scope is active inside the delegate execution.
- Route variable creation through the taskService/runtimeService with an explicit taskId/executionId.
- If a placeholder scope is genuinely needed, implement a custom mutable VariableScope.
Example fix
// before
scope.createVariableLocal("draft", value);
// after
if (scope instanceof EmptyVariableScope) {
throw new IllegalStateException("Cannot create variables on an empty scope");
}
scope.createVariableLocal("draft", value); Defensive patterns
Strategy: type-guard
Validate before calling
if (scope instanceof EmptyVariableScope) {
throw new IllegalStateException("Cannot create local variables on empty scope");
} Type guard
boolean isWritableScope(VariableScope scope) {
return scope != null && !(scope instanceof EmptyVariableScope);
} Try / catch
try {
scope.createVariableLocal(name, value);
} catch (UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().contains("Empty object")) {
logger.warn("Create skipped: empty scope");
} else {
throw e;
}
} Prevention
- Create variables via the live delegate scope during execution.
- For detached contexts use taskService/runtimeService create-variable operations with ids.
- Check instanceof EmptyVariableScope in any generic variable helper.
- Do not assume every VariableScope handed to your code is mutable.
When it happens
Trigger: Calling createVariableLocal(name, value) on an EmptyVariableScope instance.
Common situations: Delegate or listener code creating task-local variables when the received scope is the empty sentinel; init code that assumes a live TaskEntity but receives a detached/ended scope.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Empty object, no variables can be removed
- Empty object, no variables can be set
- can't clear configuration beans
- can't search values in configuration beans
- Cannot change fixed value with
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/9c98e1b6a1d29cc6.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-variable-service-api/src/main/java/org/flowable/variable/api/delegate/EmptyVariableScope.java:201
}
@Override
public boolean hasVariablesLocal() {
return false;
}
@Override
public boolean hasVariable(String variableName) {
return false;
}
@Override
public boolean hasVariableLocal(String variableName) {
return false;
}
public void createVariableLocal(String variableName, Object value) {
throw new UnsupportedOperationException("Empty object, no variables can be created");
}
public void createVariablesLocal(Map<String, ? extends Object> variables) {
throw new UnsupportedOperationException("Empty object, no variables can be created");
}
@Override
public void removeVariable(String variableName) {
throw new UnsupportedOperationException("Empty object, no variables can be removed");
}
@Override
public void removeVariableLocal(String variableName) {
throw new UnsupportedOperationException("Empty object, no variables can be removed");
}
@Override
public void removeVariables() {View on GitHub (pinned to d6d39ce1c6)