Activiti/Activiti · error · ELException

error.value.set.rvalue

error.value.set.rvalue

Error message

Cannot set value of a non-lvalue expression ''{0}''

What it means

In Activiti JUEL, AstText nodes represent literal text in an EL expression and are always read-only. setValue() is implemented to unconditionally throw ELException because a literal has no writable storage; assigning a value to it is meaningless.

Solutions

  1. Ensure the expression actually resolves to a variable or property (e.g. ${myBean.value}), not a literal or plain text.
  2. Use createValueExpression with a proper identifier/property expression before calling setValue().
  3. Check isReadOnly() on the ValueExpression before calling setValue() and handle read-only expressions gracefully.

Example fix

// before
ValueExpression ve = factory.createValueExpression(ctx, "'static text'", String.class);
ve.setValue(ctx, "new value"); // throws

// after
ValueExpression ve = factory.createValueExpression(ctx, "${myBean.text}", String.class);
ve.setValue(ctx, "new value");
Defensive patterns

Strategy: try-catch

Validate before calling

if (expr instanceof ValueExpression && !((ValueExpression) expr).isReadOnly(ctx)) { /* safe to setValue */ }

Type guard

boolean isWritable(ValueExpression ve, ELContext ctx) { return ve != null && !ve.isReadOnly(ctx); }

Try / catch

try { ve.setValue(ctx, value); } catch (ELException e) { log.warn("Expression is read-only (literal): {}", ve.getExpressionString()); }

Prevention

When it happens

Trigger: Calling ExpressionFactory.createValueExpression(literalText, ...) and then invoking setValue() on the resulting ValueExpression, e.g. elFactory.createValueExpression(context, "'hello'", Object.class).setValue(ctx, newValue) where the expression parses to an AstText node rather than an identifier or property.

Common situations: Templates or dynamically built expressions where a variable name was accidentally quoted or the expression is plain text; code that assumes any ValueExpression is writable; refactoring that swapped a #{bean.property} expression for a literal string.

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 Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/932be95ce8f888e0. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core-common/activiti-juel-jakarta/src/main/java/org/activiti/core/el/juel/tree/impl/ast/AstText.java:54

    public boolean isLeftValue() {
        return false;
    }

    public boolean isMethodInvocation() {
        return false;
    }

    public Class<?> getType(Bindings bindings, ELContext context) {
        return null;
    }

    public boolean isReadOnly(Bindings bindings, ELContext context) {
        return true;
    }

    public void setValue(Bindings bindings, ELContext context, Object value) {
        throw new ELException(LocalMessages.get("error.value.set.rvalue", getStructuralId(bindings)));
    }

    public ValueReference getValueReference(Bindings bindings, ELContext context) {
        return null;
    }

    @Override
    public Object eval(Bindings bindings, ELContext context) {
        return value;
    }

    public MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {
        return null;
    }

    public Object invoke(
        Bindings bindings,
        ELContext context,

View on GitHub (pinned to 56435b1a97)