flowable/flowable-engine · error · MethodNotFoundException
Unable to find unambiguous method
Error message
Unable to find unambiguous method: ${clazz}.${name}(${paramString(paramTypes)}) What it means
Flowable's EL method resolver throws MethodNotFoundException when more than one method on the target class matches the expression's parameter count/types equally, so no unambiguous best match exists. Rather than guessing, the resolver fails fast. This mirrors the ambiguity handling in Tomcat's org.apache.el.util.ReflectionUtil.
Solutions
- Rename one of the ambiguous overloaded methods or use distinct method names in expressions
- Cast or coerce the argument explicitly in the expression so exactly one overload matches
- Pass arguments whose runtime types unambiguously select a single overload
Example fix
// before: bean has handle(String) and handle(Integer), expression arg type ambiguous
${taskService.handle(value)}
// after: dedicated method avoids ambiguity
${taskService.handleString(value)} Defensive patterns
Strategy: validation
Validate before calling
long matches = Arrays.stream(clazz.getMethods()).filter(m -> m.getName().equals(name) && isApplicable(m, argValues)).count();
if (matches > 1) throw new IllegalStateException("Ambiguous EL method: " + name); Try / catch
try { method = Util.findMethod(context, clazz, base, name, argTypes, args); } catch (MethodNotFoundException e) { if (e.getMessage().startsWith("Unable to find unambiguous")) { log.warn("Ambiguous overload for {}", name); } throw e; } Prevention
- Avoid overloaded method names on beans exposed to EL expressions
- Pass explicitly typed arguments in expressions
- When adding overloads, grep deployed models for existing references
When it happens
Trigger: Evaluating an EL method expression where the target class has overloaded methods with equal match quality for the supplied argument types, e.g. two overloads both applicable after coercion, reached via Util.findWrapper from Util.result.
Common situations: Overloaded service methods (e.g. foo(String) and foo(Integer)) invoked with an EL expression whose argument type is ambiguous (null literal, or a value EL coerces either way); adding an overload to a bean that is also referenced from existing process expressions.
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
- Cannot coerce property to array index:
- Cannot find method with parameters in
- Cannot parse array index:
- Cannot write property
- Cannot write property
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/70a690131a177af3.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/Util.java:255
} else if (cmp == 0) {
ambiguousCandidates.add(entry.getKey());
multiple = true;
}
}
if (multiple) {
if (bestMatch.getExactCount() == paramCount - 1) {
// Only one parameter is not an exact match - try using the
// super class
String errorMsg = "Unable to find unambiguous method: " + clazz + "." + name + "(" + paramString(paramTypes) + ")";
match = findMostSpecificWrapper(ambiguousCandidates, paramTypes, bestMatch.getAssignableCount() > 0, errorMsg);
} else {
match = null;
}
if (match == null) {
// If multiple methods have the same matching number of parameters
// the match is ambiguous so throw an exception
throw new MethodNotFoundException("Unable to find unambiguous method: " + clazz + "." + name + "(" + paramString(paramTypes) + ")");
}
}
// Handle case where no match at all was found
if (match == null) {
throw new MethodNotFoundException("Method not found: " + clazz + "." + name + "(" + paramString(paramTypes) + ")");
}
return match;
}
/*
* This method duplicates code in com.sun.el.util.ReflectionUtil. When making changes keep the code in sync.
*/
private static <T> Wrapper<T> findMostSpecificWrapper(Collection<Wrapper<T>> candidates, Class<?>[] matchingTypes, boolean elSpecific, String errorMsg) {
List<Wrapper<T>> ambiguouses = new ArrayList<>();
for (Wrapper<T> candidate : candidates) {
boolean lessSpecific = false;View on GitHub (pinned to d6d39ce1c6)