{"record":{"id":"2f7b055c98d5a035","repo":"flowable/flowable-engine","slug":"error-value-set-rvalue-2f7b05","errorCode":null,"errorMessage":"error.value.set.rvalue","messagePattern":"error\\.value\\.set\\.rvalue","errorType":"exception","errorClass":"ELException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstRightValue.java","lineNumber":58,"sourceCode":"\t@Override\n\tpublic final Class<?> getType(Bindings bindings, ELContext context) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * non-lvalues are always readonly, so answer <code>true</code>\n\t */\n\t@Override\n\tpublic final boolean isReadOnly(Bindings bindings, ELContext context) {\n\t\treturn true;\n\t}\n\n\t/**\n\t * non-lvalues are always readonly, so throw an exception\n\t */\n\t@Override\n\tpublic final void setValue(Bindings bindings, ELContext context, Object value) {\n\t\tthrow new ELException(LocalMessages.get(\"error.value.set.rvalue\", getStructuralId(bindings)));\n\t}\n\n\t@Override\n\tpublic final MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic final Object invoke(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes, Object[] paramValues) {\n\t\tthrow new ELException(LocalMessages.get(\"error.method.invalid\", getStructuralId(bindings)));\n\t}\n\n\t@Override\n\tpublic final boolean isLeftValue() {\n\t\treturn false;\n\t}\n\t\n\t@Override","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstRightValue.java#L40-L76","documentation":"AstRightValue represents non-assignable (rvalue) expression nodes in the embedded JUEL/odysseus EL parser. Its setValue is always final and always throws ELException because an rvalue can never be an assignment target. Flowable throws it when a script or expression tries to write a value into something that is not a variable.","triggerScenarios":"Calling ELContext/ExpressionNode setValue (or a ValueExpression.setValue) whose AST root is a right-value node, e.g. setting into a method result, literal, or operator expression like '${a + b}' or '${myBean.getText()}' inside an expression assignment (e.g. flowable:expression used as write target, or delegating expression code calling setValue on the ValueExpression).","commonSituations":"BPMN process models where an expression is used on the left side of an assignment; misreading `${...}` expressions as settable properties; trying to mutate read-only bean properties via expression in a task listener or service task field injection.","solutions":["Write to an actual variable instead: use delegateTask.setVariable / runtimeService.setVariable, or a left-value expression like a bare variable or property path.","If the target is a bean property, expose a setter and use the property path '${myBean.text}' as the lvalue rather than a method call or computed expression.","Verify the parsed expression root: check isLeftValue() on the node or use AST introspection before calling setValue."],"exampleFix":"// before\nexpression.setValue(bindings, context, \"newValue\"); // ${order.total} -> ELException\n// after\nruntimeService.setVariable(execution.getId(), \"orderTotal\", \"newValue\");","handlingStrategy":"type-guard","validationCode":"if (valueExpression.isReadOnly(context)) { throw new IllegalArgumentException(\"Expression is not assignable: \" + valueExpression.getExpressionString()); }","typeGuard":"boolean isAssignable(ValueExpression ve, ELContext ctx) { return ve != null && !ve.isReadOnly(ctx); }","tryCatchPattern":"try { ve.setValue(ctx, value); } catch (ELException e) { log.error(\"Cannot assign to rvalue expression {}: {}\", ve.getExpressionString(), e.getMessage()); }","preventionTips":["Only call setValue on bare variable or property-path expressions","Prefer engine setVariable APIs over EL assignment","Check isReadOnly() before assignment"],"tags":["el","expression","readonly","assignment"],"backgroundTag":"unsupported-operation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}