spring-projects/spring-framework · error · AopInvocationException

Mismatch on arguments to advice method

Error message

Mismatch on arguments to advice method [{}]; pointcut expression [{}]

What it means

Thrown by invokeAdviceMethodWithGivenArgs (line 650-654) as an AopInvocationException wrapping an IllegalArgumentException from Method.invoke. The underlying cause is that the assembled argument array does not match the advice method's formal parameters at reflective invocation time (wrong count or incompatible types). The message includes both the advice method and the pointcut expression to aid diagnosis.

Solutions

  1. Inspect the wrapped IllegalArgumentException cause to see which argument failed type conversion.
  2. Make the advice parameter type a supertype of the bound value (e.g. Object instead of a narrow type).
  3. For returning, use a type restriction that matches the actual return type, or widen the parameter.
  4. Verify args()/this()/target() bindings correspond in type and order to the advice parameters.

Example fix

// before — parameter type narrower than bound value
@AfterReturning(pointcut="execution(* svc.*(..))", returning="r")
public void after(String r) { ... } // but target returns Integer -> ClassCastException at invoke

// after — widen the parameter type
@AfterReturning(pointcut="execution(* svc.*(..))", returning="r")
public void after(Object r) { ... }
Defensive patterns

Strategy: try-catch

Validate before calling

import java.lang.reflect.Method;

// Pre-check assignable types between bound values and advice params (best-effort for returning).
void assertReturningTypeCompatible(Method adviceMethod, String returningName, Class<?> returnType) {
    String[] names = new org.springframework.core.DefaultParameterNameDiscoverer().getParameterNames(adviceMethod);
    Class<?>[] types = adviceMethod.getParameterTypes();
    for (int i = 0; names != null && i < names.length; i++) {
        if (names[i].equals(returningName) && !types[i].isAssignableFrom(returnType)) {
            throw new IllegalStateException("returning param type " + types[i] + " cannot accept " + returnType);
        }
    }
}

Type guard

boolean returningTypeAccepts(Method m, String returningName, Class<?> returnType) {
    String[] names = new org.springframework.core.DefaultParameterNameDiscoverer().getParameterNames(m);
    Class<?>[] types = m.getParameterTypes();
    for (int i = 0; names != null && i < names.length; i++) {
        if (names[i].equals(returningName)) return types[i].isAssignableFrom(returnType);
    }
    return false;
}

Try / catch

import org.springframework.aop.AopInvocationException;
try {
    proxy.businessMethod();
} catch (AopInvocationException ex) {
    // ex.getMessage() contains the advice method + pointcut expression;
    // cause is IllegalArgumentException naming the offending argument
    Throwable cause = ex.getCause();
    // widen the parameter type or fix the binding, then retry
}

Prevention

When it happens

Trigger: The bound argument values (from pointcut match + returning + throwing) have types incompatible with the advice method's declared parameter types — e.g. an args() binding yields a String but the parameter is Integer, or returning binds a value whose runtime type is not assignable to the declared parameter type. Distinct from error [11] (which is about count); this is about the reflective invoke failing.

Common situations: Pointcut binds a variable whose runtime type does not match the advice parameter type, the returning type restriction is looser than the parameter, or a generic/erasure mismatch. Common after changing a target method's signature so the bound value's type changes, or after a refactoring that alters which value an args() variable captures.

Related errors


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

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:651

	protected @Nullable Object invokeAdviceMethodWithGivenArgs(@Nullable Object[] args) throws Throwable {
		@Nullable Object[] actualArgs = args;
		if (this.aspectJAdviceMethod.getParameterCount() == 0) {
			actualArgs = null;
		}
		Object aspectInstance = this.aspectInstanceFactory.getAspectInstance();
		if (aspectInstance.equals(null)) {
			// Possibly a NullBean -> simply proceed if necessary.
			if (getJoinPoint() instanceof ProceedingJoinPoint pjp) {
				return pjp.proceed();
			}
			return null;
		}
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			return this.aspectJAdviceMethod.invoke(aspectInstance, actualArgs);
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("Mismatch on arguments to advice method [" +
					this.aspectJAdviceMethod + "]; pointcut expression [" +
					this.pointcut.getPointcutExpression() + "]", ex);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}

	/**
	 * Overridden in around advice to return proceeding join point.
	 */
	protected JoinPoint getJoinPoint() {
		return currentJoinPoint();
	}

	/**
	 * Get the current join point match at the join point we are being dispatched on.
	 */

View on GitHub (pinned to 69bf83ad71)