flowable/flowable-engine · error · UnsupportedOperationException
Setting variable is not supported for read only delegate exe
Error message
Setting variable is not supported for read only delegate execution
What it means
ReadOnlyDelegatePlanItemInstance.setVariable throws UnsupportedOperationException by default: this plan-item-instance view is read-only and forbids variable mutation. The engine hands listeners/delegates a read-only facade when writes are not permitted (e.g. read-only evaluation contexts in CMMN), so variable writes must go through a writable execution instead.
Source
Thrown at modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/delegate/ReadOnlyDelegatePlanItemInstance.java:38
/**
* @author Filip Hrisafov
*/
public interface ReadOnlyDelegatePlanItemInstance extends PlanItemInstance, VariableContainer {
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
- Write variables through engine services instead: cmmnRuntimeService.setVariable(caseInstanceId, name, value).
- Obtain a writable DelegatePlanItemInstance/ plan item instance from the runtime service and set variables there.
- Restructure the listener so variable changes happen in a phase/context where a mutable delegate is provided.
- Split shared code paths: for read-only contexts, read variables; perform writes only with an explicit id via the runtime service.
Example fix
// before
readOnlyPlanItemInstance.setVariable("status", "done"); // throws
// after
cmmnRuntimeService.setVariable(planItemInstance.getCaseInstanceId(), "status", "done"); Defensive patterns
Strategy: try-catch
Validate before calling
if (planItemInstance instanceof org.flowable.cmmn.api.delegate.ReadOnlyDelegatePlanItemInstance) {
cmmnRuntimeService.setVariable(caseInstanceId, name, value);
} else {
planItemInstance.setVariable(name, value);
} Type guard
boolean isReadOnlyDelegate(DelegatePlanItemInstance p) {
return p instanceof org.flowable.cmmn.api.delegate.ReadOnlyDelegatePlanItemInstance;
} Try / catch
try {
planItemInstance.setVariable(name, value);
} catch (UnsupportedOperationException e) {
cmmnRuntimeService.setVariable(caseInstanceId, name, value); // writable path
} Prevention
- In CMMN listeners, never assume the provided plan item instance is mutable.
- Write case variables through CmmnRuntimeService with explicit caseInstanceId.
- Separate read-only inspection code from variable-writing code paths.
- Check the Flowable version/ listener contract: read-only delegates are handed to some callbacks by design.
When it happens
Trigger: Calling setVariable(...) (or setTransientVariable) on a ReadOnlyDelegatePlanItemInstance passed into a CMMN plan-item listener/ delegate where the engine supplies a read-only delegate.
Common situations: Writing variables from a CMMN TaskListener/ PlanItemLifecycleListener that receives a read-only plan item instance; code shared between process (BPMN) and case (CMMN) listeners assuming mutable execution; version changes where listeners became read-only.
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
- planItemInstanceId is null
- planItemInstanceId is null
- variableName is null
- plan item instance ${planItemInstanceId} doesn't exist
- planItemInstanceId is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8e7b5558836228fb.
Report an issue: GitHub.