flowable/flowable-engine · error · ActivitiException
Cannot set value of ' ', it's readonly!
Error message
Cannot set value of '${property}', it's readonly! What it means
ReadOnlyMapELResolver exposes a wrapped Map to EL as read-only. Its setValue throws ActivitiException whenever the EL expression attempts to write a property that exists in the wrapped map, enforcing that the map cannot be modified from expressions.
Solutions
- Remove the assignment from the expression; read-only maps are for reads only
- Write through runtimeService.setVariable / execution.setVariable instead of EL assignment
- If mutation is intended, pass a mutable map or a real VariableScope rather than the read-only resolver
Example fix
// before (EL)
${myVar = 'newValue'}
// after (Java)
runtimeService.setVariable(executionId, "myVar", "newValue"); Defensive patterns
Strategy: validation
Validate before calling
// Validate the EL does not assign to read-only map keys before evaluation
if (expression != null && expression.matches(".*\\$\\{[^}]*=[^}]*\\}.*")) {
throw new IllegalArgumentException("Assignments in EL are not allowed on read-only maps");
} Try / catch
try {
expressionManager.createExpression(expr).getValue(scope);
} catch (ActivitiException e) {
if (e.getMessage() != null && e.getMessage().contains("it's readonly")) {
// write via runtimeService.setVariable instead
}
} Prevention
- Never assign to keys of maps exposed through ReadOnlyMapELResolver in expressions
- Use runtimeService/execution setVariable APIs for writes
- Distinguish read-only snapshots from mutable variable scopes in expression design
When it happens
Trigger: An EL expression performing an assignment (e.g. ${myMap.key = 'value'} or c:set-style writes) on a base object that is the read-only map with a matching key.
Common situations: Scripts/delegates trying to mutate engine-provided read-only maps (e.g. process variables snapshots, variables maps passed read-only into expressions); accidentally confusing a read-only view with a variable scope.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot coerce property to array index:
- Cannot find method with parameters in
- Cannot parse array index:
- Cannot set value of '', it's readonly!
- Cannot write property
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1c6a4431b4cf1258.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/el/ReadOnlyMapELResolver.java:56
if (base == null) {
if (wrappedMap.containsKey(property)) {
context.setPropertyResolved(true);
return wrappedMap.get(property);
}
}
return null;
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object value) {
if (base == null) {
if (wrappedMap.containsKey(property)) {
throw new ActivitiException("Cannot set value of '" + property + "', it's readonly!");
}
}
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object arg) {
return Object.class;
}
@Override
public Class<?> getType(ELContext context, Object arg1, Object arg2) {
return Object.class;
}
}
View on GitHub (pinned to d6d39ce1c6)