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

  1. Check for EmptyVariableScope before creating and fetch the live task/execution via its id.
  2. Create local variables while the scope is active inside the delegate execution.
  3. Route variable creation through the taskService/runtimeService with an explicit taskId/executionId.
  4. 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

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


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)