spring-projects/spring-framework · error · IllegalArgumentException
Invalid method signature: unable to resolve type
Error message
Invalid method signature: unable to resolve type [{parameterTypeName}] for argument {i}. Root cause: {ex} What it means
Thrown as IllegalArgumentException by resolveSignature at BeanUtils.java:479 when a parameter type name inside the signature cannot be resolved to a Class via ClassUtils.forName(parameterTypeName, classLoader). It names the offending type, the argument index, and the root cause (typically ClassNotFoundException). All argument types must be fully resolvable on the target's classloader.
Solutions
- Use the fully-qualified type name, e.g. "doStuff(java.lang.String, java.lang.Integer)".
- Ensure the referenced type's JAR/class is on the runtime classpath of the resolving classloader.
- After a rename/refactor, update all string-based method signatures.
- If short names are desired, resolve them to FQCNs yourself before calling resolveSignature.
Example fix
// before
Method m = BeanUtils.resolveSignature("doStuff(String, Integer)", clazz);
// after
Method m = BeanUtils.resolveSignature("doStuff(java.lang.String, java.lang.Integer)", clazz); Defensive patterns
Strategy: validation
Validate before calling
// Validate each type name resolves on the target classloader first
String sig = "doStuff(java.lang.String, java.lang.Integer)";
for (String t : sig.substring(sig.indexOf('(')+1, sig.indexOf(')')).split(",")) {
ClassUtils.forName(t.trim(), clazz.getClassLoader());
}
BeanUtils.resolveSignature(sig, clazz); Type guard
static boolean allTypesResolvable(String sig, ClassLoader cl) {
String args = sig.substring(sig.indexOf('(')+1, sig.indexOf(')'));
for (String t : args.split(",")) {
if (t.isBlank()) continue;
try { ClassUtils.forName(t.trim(), cl); }
catch (Throwable e) { return false; }
}
return true;
} Try / catch
try {
BeanUtils.resolveSignature(sig, clazz);
} catch (IllegalArgumentException ex) {
if (ex.getMessage().contains("unable to resolve type")) {
// rewrite short names to FQCNs and ensure jars present
sig = sig.replace("String", "java.lang.String");
} else throw ex;
} Prevention
- Use fully-qualified type names in method signature strings.
- Keep referenced types on the runtime classpath of the resolving classloader.
- Update signature strings after class renames/moves.
- Resolve short type names to FQCNs before calling resolveSignature.
When it happens
Trigger: Calling resolveSignature("doStuff(com.missing.Type)", clazz) where com.missing.Type is not on the classpath; using unqualified type names that ClassUtils.forName cannot resolve (it expects fully-qualified names, with limited primitive/array shortcuts); passing a type from another module/classloader not visible here.
Common situations: Config-driven method invocation referencing types not present at runtime; refactor that renamed/moved a class without updating the string signature; classloader isolation in app servers/OSGi; using short names like 'String' instead of 'java.lang.String' (forName does not import packages).
Related errors
- Invalid method signature
- Invalid method signature
- Unresolvable class definition
- Cannot resolve method
- Constructor threw exception
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/d7299c0afc578757.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:479
else if (startParen == -1 && endParen > -1) {
throw new IllegalArgumentException("Invalid method signature '" + signature +
"': expected opening '(' for args list");
}
else if (startParen == -1) {
return findMethodWithMinimalParameters(clazz, signature);
}
else {
String methodName = signature.substring(0, startParen);
String[] parameterTypeNames =
StringUtils.commaDelimitedListToStringArray(signature.substring(startParen + 1, endParen));
Class<?>[] parameterTypes = new Class<?>[parameterTypeNames.length];
for (int i = 0; i < parameterTypeNames.length; i++) {
String parameterTypeName = parameterTypeNames[i].trim();
try {
parameterTypes[i] = ClassUtils.forName(parameterTypeName, clazz.getClassLoader());
}
catch (Throwable ex) {
throw new IllegalArgumentException("Invalid method signature: unable to resolve type [" +
parameterTypeName + "] for argument " + i + ". Root cause: " + ex);
}
}
return findMethod(clazz, methodName, parameterTypes);
}
}
/**
* Retrieve the JavaBeans {@code PropertyDescriptor}s of a given class.
* @param clazz the Class to retrieve the PropertyDescriptors for
* @return an array of {@code PropertyDescriptors} for the given class
* @throws BeansException if PropertyDescriptor look fails
*/
public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException {
return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors();
}
View on GitHub (pinned to 69bf83ad71)