flowable/flowable-engine · error · ELException

ELException

Error message

ELException

What it means

BeanELResolver.getValue throws a bare ELException (no message, cause attached) when any non-InvocationTargetException Exception occurs while reading a bean property — e.g. IllegalAccessException on an inaccessible getter.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/BeanELResolver.java:160

		}

		BeanProperty beanProperty = property(base, property);
		if (beanProperty == null) {
			return null;
		}
		Method m = beanProperty.read(base);
		if (m == null) {
			return null;
		}
		context.setPropertyResolved(base, property);
		try {
			return invoke(m, base, (Object[]) null);
		} catch (InvocationTargetException e) {
			Throwable cause = e.getCause();
			Util.handleThrowable(cause);
            throw new ELException("Error reading '" + property + "' on type '" + base.getClass().getName() + "'", cause);
		} catch (Exception e) {
			throw new ELException(e);
		}
	}

	@Override
	public void setValue(ELContext context, Object base, Object property, Object value) {
		Objects.requireNonNull(context, "context is null");
		if (base == null || property == null) {
			return;
		}

		if (readOnly) {
			throw new PropertyNotWritableException("resolver is read-only");
		}
		BeanProperty beanProperty = property(base, property);

		if (beanProperty == null) {
			return;
		}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Open the `--add-opens`/module exports for the bean's package, or make the bean class public.
  2. Add a public getter for the referenced property.
  3. Read the ELException's cause to identify the exact reflective failure.

Example fix

// before
class InternalBean { public String getId() {...} } // package-private class
// after
public class InternalBean { public String getId() {...} }
Defensive patterns

Strategy: type-guard

Validate before calling

Method m = new PropertyDescriptor(prop, bean.getClass()).getReadMethod(); if (m != null && !Modifier.isPublic(m.getDeclaringClass().getModifiers())) throw new IllegalStateException("declaring class not accessible");

Type guard

boolean readableViaEl(Object bean, String prop) { try { PropertyDescriptor pd = new PropertyDescriptor(prop, bean.getClass()); return pd.getReadMethod() != null && Modifier.isPublic(pd.getReadMethod().getModifiers()); } catch (IntrospectionException e) { return false; } }

Try / catch

try { v = resolver.getValue(ctx, bean, prop); } catch (ELException e) { /* check cause: IllegalAccessException -> open module / make class public */ }

Prevention

When it happens

Trigger: Evaluating ${bean.property} where the getter method exists but cannot be reflectively invoked: non-public getter class without accessible override, security manager restrictions, or generic reflective invocation failures.

Common situations: Package-private or private classes with public getters (reflection needs the declaring class accessible); Java module/JPMS encapsulation blocking reflective access.

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 flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/f3cc495f696c518e. Report an issue: GitHub.