flowable/flowable-engine · error · ELException

error.method.invalid

error.method.invalid

Error message

error.method.invalid

What it means

TreeMethodExpression requires that a non-literal expression which is not a method invocation must at least be a left value (an assignable l-value). If the expression is neither a method invocation nor a left value, construction fails with 'error.method.invalid'.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/TreeMethodExpression.java:92

		super();

		Tree tree = store.get(expr);

		this.builder = store.getBuilder();
		this.bindings = tree.bind(functions, variables, converter);
		this.expr = expr;
		this.type = returnType;
		this.types = paramTypes;
		this.node = tree.getRoot();
		this.deferred = tree.isDeferred();

		if (node.isLiteralText()) {
			if (returnType == void.class || returnType == Void.class) {
				throw new ELException(LocalMessages.get("error.method.literal.void", expr));
			}
		} else if (!node.isMethodInvocation()) {
			if (!node.isLeftValue()) {
				throw new ELException(LocalMessages.get("error.method.invalid", expr));
			}
			if (paramTypes == null) {
				throw new NullPointerException(LocalMessages.get("error.method.notypes")); // EL specification requires NPE
			}
		}
	}

	private String getStructuralId() {
		if (structure == null) {
			structure = node.getStructuralId(bindings);
		}
		return structure;
	}
	
  /**
   * Evaluates the expression and answers information about the method
   * @param context used to resolve properties (<code>base.property</code> and <code>base[property]</code>)
   * @return method information or <code>null</code> for literal expressions

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Correct the expression to a valid method invocation, e.g. '#{bean.method(...)}'.
  2. If you meant a value binding, use TreeValueExpression instead of TreeMethodExpression.
  3. Verify the parsed expression resolves to an l-value (property access) if intended as an l-value method target.

Example fix

// before
new TreeMethodExpression(store, ctx, fns, vars, "#{bean.prop + 1}", null, Object.class)
// after
new TreeMethodExpression(store, ctx, fns, vars, "#{bean.compute()}", null, Object.class)
Defensive patterns

Strategy: validation

Validate before calling

// parse-check: expression must be a method invocation or an l-value
if (!expr.matches("#\{[^}]+\}") && !expr.matches("\$\{[^}]+\}")) {
    // literal is ok, else it must resolve to a method or l-value at construction
}

Type guard

boolean isValidMethodExpression(String expr) {
    return expr.startsWith("#{") && expr.contains("("); // method invocation form
}

Try / catch

try {
    TreeMethodExpression m = new TreeMethodExpression(store, ctx, fns, vars, expr, paramTypes, returnType);
} catch (ELException e) {
    // expression is neither a method invocation nor an l-value; fix the expression
}

Prevention

When it happens

Trigger: new TreeMethodExpression(...) with an expression like '#{a.b.c}' that resolves to something that is neither a method call nor an assignable property (e.g. an arithmetic result or a nested non-lvalue path).

Common situations: Typo in an expression (missing method name or parentheses); passing a value expression string where a method expression is required; version upgrades tightening validation.

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


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