spring-projects/spring-framework · warning · IllegalArgumentException

Invalid method signature '{signature}': expected closing ')'

Error message

Invalid method signature '{signature}': expected closing ')' for args list

What it means

Thrown as IllegalArgumentException by resolveSignature at BeanUtils.java:458 when the signature string contains an opening '(' but no matching closing ')'. The method expects 'name(arg,type,...)' form; a stray open paren without a close breaks parsing, so it refuses to guess and reports exactly which delimiter is missing.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:458

	 * 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.
	 * <p>If no method can be found, then {@code null} is returned.
	 * @param signature the method signature as String representation
	 * @param clazz the class to resolve the method signature against
	 * @return the resolved Method
	 * @see #findMethod
	 * @see #findMethodWithMinimalParameters
	 */
	public static @Nullable Method resolveSignature(String signature, Class<?> clazz) {
		Assert.hasText(signature, "'signature' must not be empty");
		Assert.notNull(clazz, "Class must not be null");
		int startParen = signature.indexOf('(');
		int endParen = signature.indexOf(')');
		if (startParen > -1 && endParen == -1) {
			throw new IllegalArgumentException("Invalid method signature '" + signature +
					"': expected closing ')' for args list");
		}
		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());

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Correct the signature to include the closing parenthesis, e.g. "doStuff()".
  2. Validate the signature has balanced parentheses before calling resolveSignature.
  3. If you only want name-based lookup with minimal params, omit the parentheses entirely: "doStuff".

Example fix

// before
Method m = BeanUtils.resolveSignature("doStuff(", clazz);

// after
Method m = BeanUtils.resolveSignature("doStuff()", clazz);
Defensive patterns

Strategy: validation

Validate before calling

int open = signature.indexOf('('), close = signature.indexOf(')');
if (open == -1 && close == -1) {
    // name-only lookup is fine
} else if (open > -1 && close > open) {
    BeanUtils.resolveSignature(signature, clazz);
} else {
    throw new IllegalArgumentException("malformed signature: " + signature);
}

Type guard

static boolean wellFormedSignature(String s) {
    int o = s.indexOf('('), c = s.indexOf(')');
    return (o == -1 && c == -1) || (o > -1 && c > o);
}

Try / catch

try {
    BeanUtils.resolveSignature(sig, clazz);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().contains("closing ')'")) {
        sig = sig + ")"; // or fix the source of the signature
    } else throw ex;
}

Prevention

When it happens

Trigger: Calling BeanUtils.resolveSignature("doStuff(", clazz) or "doStuff(a, b" — any signature where '(' appears but ')' does not. Common when concatenating/truncating a method signature string programmatically or in a typo'd XML/annotation value.

Common situations: Method-invocation / SpEL method lookups configured via strings; generated config that builds a signature and truncates it; copy-paste errors in @Bean/@Pointcut-like name expressions; YAML/properties whose value gets trimmed wrong.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/df62642ca307ff6d. Report an issue: GitHub.