flowable/flowable-engine · error · MethodNotFoundException
error.identifier.method.notamethod
Error message
error.identifier.method.notamethod
What it means
AstIdentifier.getMethodExpression resolves an identifier to a method to invoke. If the bound value is neither a Java method/FunctionMapper result nor a MethodExpression, it throws MethodNotFoundException naming the identifier and the actual value class. It means the EL expression calls something like ${name(args)} but 'name' resolved to an ordinary object that is not callable.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/ast/AstIdentifier.java:196
try {
return method.invoke(null, params);
} catch (IllegalAccessException e) {
throw new ELException(LocalMessages.get("error.identifier.method.access", name), e);
} catch (IllegalArgumentException e) {
throw new ELException(LocalMessages.get("error.identifier.method.invocation", name, e));
} catch (InvocationTargetException e) {
throw new ELException(LocalMessages.get("error.identifier.method.invocation", name, e.getCause()));
}
}
@Override
public MethodInfo getMethodInfo(ELContext context) {
return new MethodInfo(method.getName(), method.getReturnType(), method.getParameterTypes());
}
};
} else if (value instanceof MethodExpression) {
return (MethodExpression)value;
}
throw new MethodNotFoundException(LocalMessages.get("error.identifier.method.notamethod", name, value.getClass()));
}
@Override
public MethodInfo getMethodInfo(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes) {
return getMethodExpression(bindings, context, returnType, paramTypes).getMethodInfo(context);
}
@Override
public Object invoke(Bindings bindings, ELContext context, Class<?> returnType, Class<?>[] paramTypes, Object[] params) {
return getMethodExpression(bindings, context, returnType, paramTypes).invoke(context, params);
}
@Override
public String toString() {
return name;
}
@Override View on GitHub (pinned to d6d39ce1c6)
Solutions
- Fix the expression: use property access ${obj.field} instead of invoking it as a method, or call the method on the object ${obj.method(x)}.
- Ensure the identifier is actually bound to a method (register it via the ELContext FunctionMapper or bind a LambdaExpression) instead of a plain value.
- Correct the identifier spelling / variable name so it resolves to the intended callable.
- Inspect the class name in the message to see what the identifier actually resolved to and adjust bindings accordingly.
Example fix
// before
${toUpperCase(name)} // toUpperCase not a registered function
// after
${name.toUpperCase()} // method call on the value Defensive patterns
Strategy: validation
Validate before calling
Object v = factory.createValueExpression(ctx, "${name}", Object.class).getValue(context);
if (!(v instanceof java.lang.reflect.Method || v instanceof MethodExpression || v instanceof LambdaExpression)) {
throw new IllegalStateException("Identifier 'name' is not callable: " + v);
} Type guard
boolean isCallable(Object v) {
return v instanceof java.lang.reflect.Method
|| v instanceof MethodExpression
|| v instanceof LambdaExpression;
} Prevention
- Use property access syntax unless the identifier is a registered function or lambda
- Keep function/lambda registrations in one place and validate them at startup
- Check the value class printed in the message to spot binding mistakes quickly
When it happens
Trigger: Invoking an identifier as a method in EL (e.g. ${myHelper(x)}) when the bound identifier evaluates to a plain value (String, bean, null-wrapped object) rather than a method reference or MethodExpression; bindings missing a method entry because the FunctionMapper/ELResolver did not provide one.
Common situations: Typo in a function name registered via EL functions; calling a bean property as a method (writing ${obj.field()} instead of ${obj.field}); a variable bound in a process/delegation was expected to be a lambda/method but is a plain serialized value; upgrading Flowable/EL versions where method resolution via resolver was removed.
Related errors
- Cannot find method ${name} with ${params.length} parameters
- Method not found: ${clazz}.${methodName}(${paramString(param
- Method not found: ${clazz}.${name}(${paramString(paramTypes)
- error.coerce.type
- ' + token.getImage() + '
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/dc47b73d280b0434.
Report an issue: GitHub.