spring-projects/spring-framework · error · IllegalArgumentException
Cannot resolve method '${methodName}' to a unique method. At
Error message
Cannot resolve method '${methodName}' to a unique method. Attempted to resolve to overloaded method with the least number of parameters but there were ${numMethodsFoundWithCurrentMinimumArgs} candidates. What it means
Thrown as IllegalArgumentException by findMethodWithMinimalParameters / resolveSignature when more than one method with the given name share the smallest parameter count, so the 'least parameters' heuristic cannot pick a unique winner (BeanUtils.java:425-430). The count of ambiguous candidates is included in the message.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:426
int numParams = method.getParameterCount();
if (targetMethod == null || numParams < targetMethod.getParameterCount()) {
targetMethod = method;
numMethodsFoundWithCurrentMinimumArgs = 1;
}
else if (!method.isBridge() && targetMethod.getParameterCount() == numParams) {
if (targetMethod.isBridge()) {
// Prefer regular method over bridge...
targetMethod = method;
}
else {
// Additional candidate with same length
numMethodsFoundWithCurrentMinimumArgs++;
}
}
}
}
if (numMethodsFoundWithCurrentMinimumArgs > 1) {
throw new IllegalArgumentException("Cannot resolve method '" + methodName +
"' to a unique method. Attempted to resolve to overloaded method with " +
"the least number of parameters but there were " +
numMethodsFoundWithCurrentMinimumArgs + " candidates.");
}
return targetMethod;
}
/**
* Parse a method signature in the form {@code methodName[([arg_list])]},
* where {@code arg_list} is an optional, comma-separated list of fully-qualified
* type names, and attempts to resolve that signature against the supplied {@code Class}.
* <p>When not supplying an argument list ({@code methodName}) the method whose name
* matches and has the least number of parameters will be returned. When supplying an
* argument type list, only the method whose name and argument types match will be returned.
* <p>Note then that {@code methodName} and {@code methodName()} are <strong>not</strong>
* resolved in the same way. The signature {@code methodName} means the method called
* {@code methodName} with the least number of arguments, whereas {@code methodName()}
* means the method called {@code methodName} with exactly 0 arguments.View on GitHub (pinned to e8729d0438)
Solutions
- Provide the full signature with argument types in resolveSignature: 'methodName(int, java.lang.String)' to disambiguate.
- Rename one of the colliding overloads if you control the class.
- Use findMethod(clazz, name, paramTypes...) directly with explicit parameter types instead of the minimal-args heuristic.
- Reduce accidental same-arity overloads (e.g. consolidate or remove one).
Example fix
// before
resolveSignature("persist", repo.getClass()); // persist(int) & persist(String) ambiguous
// after
resolveSignature("persist(int)", repo.getClass()); Defensive patterns
Strategy: validation
Validate before calling
// Detect same-arity overload collision before resolving
long minArity = Arrays.stream(clazz.getMethods())
.filter(m -> m.getName().equals(methodName) && !m.isBridge())
.mapToInt(Method::getParameterCount).min().orElse(-1);
long count = Arrays.stream(clazz.getMethods())
.filter(m -> m.getName().equals(methodName) && !m.isBridge()
&& m.getParameterCount() == minArity).count();
if (count > 1) { /* supply full signature instead */ } Type guard
public static boolean methodResolvableByName(Class<?> c, String name) {
try { BeanUtils.findMethodWithMinimalParameters(c, name); return true; }
catch (IllegalArgumentException e) { return false; }
} Try / catch
try { BeanUtils.resolveSignature(name, clazz); }
catch (IllegalArgumentException e) {
BeanUtils.resolveSignature(name + "(int)", clazz); // disambiguate with arg types
} Prevention
- Provide the full signature 'name(argType, ...)' when overloads exist.
- Avoid same-arity overloads where possible.
- Use findMethod(clazz, name, paramTypes) with explicit types.
When it happens
Trigger: resolveSignature('methodName', clazz) with no argument list, or findMethodWithMinimalParameters(clazz, 'methodName'), where the class declares two or more overloads with the same minimal arity (e.g. foo() and foo() from different interfaces, or foo(int) and foo(String)).
Common situations: Method-resolver utilities, scheduler/transaction attribute parsing, pointcut expressions, and AOP config that take a bare method name. Class hierarchies introducing same-arity overloads. Bridge methods (note the code excludes isBridge from counting, but real overloads still collide).
Related errors
- Specified class is an interface
- Is it an abstract class?
- Is the constructor accessible?
- No default constructor found
- Unresolvable class definition
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/01c80a1507cd4972.json.
Report an issue: GitHub.