flowable/flowable-engine · error · ActivitiException

Unknown method used in expression

Error message

Unknown method used in expression: ${expressionText}

What it means

JuelExpression.getValue also catches MethodNotFoundException from the EL resolver, thrown when an expression invokes a method that doesn't exist on the resolved target (e.g. ${myBean.calculateX(1)} where calculateX is absent or has an incompatible signature). The engine wraps it in this ActivitiException with the expression text.

Solutions

  1. Check that the method exists on the target bean with the exact name and is public.
  2. Match the EL argument count and types; add overloads or convert arguments (e.g. ${bean.calc('${num}' == null ? 0 : num)}).
  3. Update BPMN expressions after refactoring method names.
  4. Remember JUEL has no varargs/autoboxing nuance — declare simpler signatures or do conversion inside the method.

Example fix

// before: BPMN calls ${orderService.getTotl(order)} but method renamed
public BigDecimal getTotal(Order o) {...}
// after: update the expression to ${orderService.getTotal(order)}
Defensive patterns

Strategy: validation

Validate before calling

// Reflection pre-check that the method exists before the task runs:
Object bean = applicationContext.getBean("orderService");
for (java.lang.reflect.Method m : bean.getClass().getMethods()) {
  if (m.getName().equals("getTotal") && m.getParameterCount() == 1) return;
}
throw new IllegalStateException("orderService.getTotal not found — expression will fail");

Try / catch

try {
  Object v = juelExpression.getValue(container);
} catch (ActivitiException e) {
  if (e.getCause() instanceof MethodNotFoundException) {
    throw new IllegalStateException("BPMN expression references missing method: " + e.getMessage());
  } else { throw e; }
}

Prevention

When it happens

Trigger: Evaluating a method-call expression ${bean.method(...)} during getValue where the method name or its parameter types do not match any method on the target object (including JUEL's limited type-coercion rules).

Common situations: Renaming a method on a delegate/bean without updating BPMN expressions, wrong number or types of arguments (EL coercion, e.g. passing a String where an int is expected), method not public, or bean of a different type than expected.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/57c103585afea57d. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/el/JuelExpression.java:57

    public JuelExpression(ValueExpression valueExpression, String expressionText) {
        this.valueExpression = valueExpression;
        this.expressionText = expressionText;
    }

    @Override
    public Object getValue(VariableContainer variableContainer) {
        ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext((VariableScope) variableContainer);
        try {
            ExpressionGetInvocation invocation = new ExpressionGetInvocation(valueExpression, elContext);
            Context.getProcessEngineConfiguration()
                    .getDelegateInterceptor()
                    .handleInvocation(invocation);
            return invocation.getInvocationResult();
        } catch (PropertyNotFoundException pnfe) {
            throw new ActivitiException("Unknown property used in expression: " + expressionText, pnfe);
        } catch (MethodNotFoundException mnfe) {
            throw new ActivitiException("Unknown method used in expression: " + expressionText, mnfe);
        } catch (ELException ele) {
            throw new ActivitiException("Error while evaluating expression: " + expressionText, ele);
        } catch (Exception e) {
            throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
        }
    }
    
    @Override
    public void setValue(Object value, VariableContainer variableContainer) {
        ELContext elContext = Context.getProcessEngineConfiguration().getExpressionManager().getElContext((VariableScope) variableContainer);
        try {
            ExpressionSetInvocation invocation = new ExpressionSetInvocation(valueExpression, elContext, value);
            Context.getProcessEngineConfiguration()
                    .getDelegateInterceptor()
                    .handleInvocation(invocation);
        } catch (Exception e) {
            throw new ActivitiException("Error while evaluating expression: " + expressionText, e);
        }

View on GitHub (pinned to d6d39ce1c6)