flowable/flowable-engine · error · UnsupportedOperationException
Setting transient variable is not supported for read only de
Error message
Setting transient variable is not supported for read only delegate execution
What it means
ReadOnlyDelegatePlanItemInstance is a default-implementation wrapper handed to CMMN delegates that must not mutate case state. All mutating methods, including setTransientVariable, throw UnsupportedOperationException by design to signal that writes are illegal in this execution context.
Source
Thrown at modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/delegate/ReadOnlyDelegatePlanItemInstance.java:43
PlanItem getPlanItem();
default PlanItemDefinition getPlanItemDefinition() {
PlanItem planItem = getPlanItem();
if (planItem != null) {
return planItem.getPlanItemDefinition();
}
return null;
}
@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");
}
@Override
default void setLocalizedName(String localizedName) {
throw new UnsupportedOperationException("Setting localized name is not supported for read only delegate execution");
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Remove the setTransientVariable call when running in a read-only context
- Detect read-only instances before writing and skip or buffer the write
- Use a different extension point (e.g. a non-read-only delegate/listener) if the write is required
- Pass required data via the delegate's input mappings/field injections instead of transient variables
Example fix
// before
public void notify(DelegatePlanItemInstance planItemInstance) {
planItemInstance.setTransientVariable("result", compute());
}
// after
public void notify(DelegatePlanItemInstance planItemInstance) {
if (!(planItemInstance instanceof ReadOnlyDelegatePlanItemInstance)) {
planItemInstance.setTransientVariable("result", compute());
}
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean canWrite = !(planItemInstance instanceof ReadOnlyDelegatePlanItemInstance);
Type guard
if (planItemInstance instanceof ReadOnlyDelegatePlanItemInstance readOnly) { /* read-only: skip writes */ } Try / catch
try { planItemInstance.setTransientVariable(name, value); } catch (UnsupportedOperationException e) { log.warn("Read-only context, skipped transient variable {}", name); } Prevention
- Never write variables from lifecycle/audit listeners that receive read-only delegates
- Pass data into delegates via field injection or input mappings instead of transient variables
- Unit-test delegates against read-only instances to surface illegal writes early
When it happens
Trigger: Calling planItemInstance.setTransientVariable(name, value) from inside a delegate (e.g. a TaskListener or PlanItemJavaDelegate) that received a read-only delegate plan item instance, typically in read-only listener contexts such as CMMN case lifecycle listeners.
Common situations: Reusing a variable-writing delegate written for normal delegates in a read-only listener; copying BPMN task code into a CMMN lifecycle listener; frameworks injecting read-only instances for audit/history listeners.
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
- Setting localized name is not supported for read only delega
- org.flowable.cdi.impl.ProcessVariableMap.size() is not suppo
- org.flowable.cdi.impl.ProcessVariableMap.isEmpty() is not su
- org.flowable.cdi.impl.ProcessVariableMap.containsKey() is no
- org.flowable.cdi.impl.ProcessVariableMap.containsValue() is
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5520e20ff5666d8b.
Report an issue: GitHub.