flowable/flowable-engine · error · UnsupportedOperationException

Setting variable is not supported for read only delegate…

Error message

Setting variable is not supported for read only delegate execution

What it means

ReadOnlyDelegateExecution is a wrapper exposing a DelegateExecution to delegate code without write access. Its default setVariable implementation always throws UnsupportedOperationException because mutating variables through this read-only view is intentionally forbidden.

Solutions

  1. Do not call setVariable on read-only executions; capture the value and set it on a mutable execution (e.g. the real DelegateExecution or runtimeService.setVariable)
  2. Check execution instanceof ReadOnlyDelegateExecution before writing
  3. Use execution.setTransientVariable only on writable executions; refactor the delegate to be side-effect free if handed a read-only view

Example fix

// before
execution.setVariable("status", "done");
// after
if (!(execution instanceof ReadOnlyDelegateExecution)) {
    execution.setVariable("status", "done");
}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean writable = !(execution instanceof ReadOnlyDelegateExecution);

Type guard

if (execution instanceof ReadOnlyDelegateExecution) { throw new IllegalStateException("read-only execution"); }

Try / catch

try { execution.setVariable(name, value); } catch (UnsupportedOperationException e) { /* route write to runtimeService or skip */ }

Prevention

When it happens

Trigger: Calling execution.setVariable(name, value) on a DelegateExecution that is actually a ReadOnlyDelegateExecution — typically from JavaDelegate/delegate code that receives a read-only execution wrapper instead of a mutable one.

Common situations: Framework code passing read-only executions to listeners or delegates (e.g. for preview/validation); calling variable writes in a context designed to be side-effect free.

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/6121eab72c60dc1a. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/delegate/ReadOnlyDelegateExecution.java:120

    /**
     * returns whether this execution is a process instance or not.
     */
    boolean isProcessInstanceType();

    /**
     * Returns whether this execution is a scope.
     */
    boolean isScope();

    /**
     * Returns whether this execution is the root of a multi instance execution.
     */
    boolean isMultiInstanceRoot();

    @Override
    default void setVariable(String variableName, Object variableValue) {
        throw new UnsupportedOperationException("Setting variable is not supported for read only delegate execution");
    }

    @Override
    default void setTransientVariable(String variableName, Object variableValue) {
        throw new UnsupportedOperationException("Setting transient variable is not supported for read only delegate execution");
    }
}

View on GitHub (pinned to d6d39ce1c6)