flowable/flowable-engine · error · ELException
error.value.set.rvalue
Error message
error.value.set.rvalue
What it means
AstMethod represents a method invocation in an EL expression, which is a transient value. Its setValue always throws ELException('error.value.set.rvalue', i.e. 'Cannot set value of an rvalue'), because you cannot assign to the result of a method call.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstMethod.java:54
@Override
public boolean isLiteralText() {
return false;
}
@Override
public Class<?> getType(Bindings bindings, ELContext context) {
return null;
}
@Override
public boolean isReadOnly(Bindings bindings, ELContext context) {
return true;
}
@Override
public void setValue(Bindings bindings, ELContext context, Object value) {
throw new ELException(LocalMessages.get("error.value.set.rvalue", getStructuralId(bindings)));
}
@Override
public MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {
return null;
}
@Override
public boolean isLeftValue() {
return false;
}
@Override
public boolean isMethodInvocation() {
return true;
}
@OverrideView on GitHub (pinned to d6d39ce1c6)
Solutions
- Replace the method-call target with a settable property expression: ${bean.name} instead of ${bean.getName()}.
- Invoke a setter method via method invocation semantics instead of setValue, e.g. evaluate ${bean.setName(value)}.
- Check isReadOnly()/isLiteralText on the ValueExpression before calling setValue.
Example fix
// before
ve.setValue(context, "x"); // ve = ${obj.getName()}
// after
// use a property expression
ValueExpression ve2 = factory.createValueExpression(ctx, "${obj.name}", String.class);
ve2.setValue(context, "x"); Defensive patterns
Strategy: validation
Validate before calling
if (valueExpression.isLiteralText() || isMethodExpression(valueExpression.getExpressionString())) {
throw new UnsupportedOperationException("Cannot set value of rvalue: " + valueExpression.getExpressionString());
}
// isMethodExpression: expression ends with ')' or contains '('
Type guard
boolean isWritablePropertyExpr(String expr) {
String e = expr.trim();
return e.startsWith("${") && !e.contains("(") && !e.endsWith(")");
} Try / catch
try {
ve.setValue(context, value);
} catch (ELException e) {
if (!e.getMessage().contains("error.value.set.rvalue") && !e.getMessage().contains("rvalue")) throw e;
// convert to a setter invocation or property assignment
} Prevention
- Assign to property paths, not method-call results
- Check isReadOnly/isLiteralText before setValue
- Use EL to invoke setters (${bean.setName(v)}) rather than setValue on calls
When it happens
Trigger: Calling ValueExpression.setValue on an expression that is a method call, e.g. setValue on ${bean.getName()}; generic framework code attempting to write through a parsed expression that is a method invocation rather than a property path.
Common situations: Binding frameworks that blindly call setValue on expressions; typos where a setter call should have been a property assignment ${bean.name = x}; EL expressions used as writable bindings when they are 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
- error.value.set.rvalue
- resolver is read-only
- Cannot write property: ${property}
- error.value.set.rvalue
- error.coerce.type
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ab7725815d10035e.
Report an issue: GitHub.