flowable/flowable-engine · error · PropertyNotWritableException
resolver is read-only
Error message
resolver is read-only
What it means
Write protection in ListELResolver.setValue: a setValue operation was attempted on a list-backed EL resolver that was created read-only. The EL expression being evaluated tried to assign to a list element, but this resolver instance does not permit mutation.
Solutions
- Construct ListELResolver with readOnly=false
- Mutate the list outside EL instead of through the read-only resolver
Example fix
// before new ListELResolver(true); // after new ListELResolver(false);
Defensive patterns
Strategy: type-guard
Validate before calling
boolean canWrite = !elResolverIsReadOnly; // construct resolver with readOnly=false if writes needed
Type guard
boolean writable(Object base) { return base instanceof java.util.List && resolverWritable; } Try / catch
try {
resolver.setValue(ctx, list, index, value);
} catch (PropertyNotWritableException e) {
list.set(index, value); // mutate outside EL
} Prevention
- Construct ListELResolver with readOnly=false when expressions may assign
- Keep assignments out of read-only evaluation contexts
- Distinguish read-only (query-time) from mutable (script-time) contexts
When it happens
Trigger: EL expression writing into a List (e.g. ${myList[0] = x}) while the resolver instance is read-only; the write path in setValue hits the readOnly flag after isResolvable(base).
Common situations: Immutable EL environments (e.g. read-only evaluation contexts in Flowable expression evaluation); constructing ListELResolver(true) by default and then attempting assignments in expressions.
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
- Cannot change fixed value with
- Cannot find property
- Cannot invoke method
- Cannot parse list index
- Cannot set value of '', it resolves to a bean defined in…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f881da679f134220.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/ListELResolver.java:86
if (idx < 0 || idx >= list.size()) {
return null;
}
return list.get(idx);
}
return null;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object value) {
Objects.requireNonNull(context, "context is null");
if (isResolvable(base)) {
context.setPropertyResolved(base, property);
@SuppressWarnings("unchecked") // Must be OK to cast to Object
List<Object> list = (List<Object>) base;
if (readOnly) {
throw new PropertyNotWritableException("resolver is read-only");
}
int idx = coerce(property);
try {
list.set(idx, value);
} catch (UnsupportedOperationException e) {
throw new PropertyNotWritableException(e);
} catch (IndexOutOfBoundsException e) {
throw new PropertyNotFoundException(e);
}
}
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
Objects.requireNonNull(context, "context is null");
if (isResolvable(base)) {View on GitHub (pinned to d6d39ce1c6)