spring-projects/spring-framework · error · IllegalStateException
Expecting to find arguments to bind by name in advice, but…
Error message
Expecting to find {} arguments to bind by name in advice, but actually found {} arguments. What it means
Thrown by bindExplicitArguments (line 471-476) when the length of the resolved argumentNames array does not equal the advice method's parameter count. Spring requires an exact 1:1 correspondence because each parameter is mapped by index to a pointcut binding. A mismatch indicates the supplied arg-names or discovered names describe a different signature than the method.
Solutions
- Make the arg-names list length equal the method parameter count (Spring auto-inserts the joinpoint slot only when argNames.length == paramCount - 1, see line 273).
- After changing an advice method signature, update arg-names to match.
- If using -parameters, remove arg-names entirely and let Spring discover them.
- Verify the pointcut binds exactly the variables named in arg-names.
Example fix
// before — arg-names count != method params (method has 2 params, names has 1)
<aop:after-returning method="after"
pointcut="execution(* *(..)) && args(payload)"
arg-names="payload" returning="ret"/>
public void after(JoinPoint jp, Object ret) {} // jp is implicit; needs ret too
// after — include all non-implicit names, or drop arg-names and compile with -parameters
<aop:after-returning method="after"
pointcut="execution(* *(..)) && args(payload)"
returning="ret"/>
public void after(JoinPoint jp, Object payload, Object ret) {} Defensive patterns
Strategy: validation
Validate before calling
import java.lang.reflect.Method;
// Ensure arg-names count matches the method parameter count (accounting for the implicit joinpoint slot).
void assertArgNamesCount(Method adviceMethod, String[] argNames) {
int pc = adviceMethod.getParameterCount();
Class<?> first = pc > 0 ? adviceMethod.getParameterTypes()[0] : null;
boolean hasImplicitJp = first == org.aspectj.lang.JoinPoint.class
|| first == org.aspectj.lang.ProceedingJoinPoint.class
|| first == org.aspectj.lang.JoinPoint.StaticPart.class;
int expected = hasImplicitJp ? pc - 1 : pc;
if (argNames.length != expected && argNames.length != pc) {
throw new IllegalStateException("arg-names count " + argNames.length + " != params " + expected);
}
} Type guard
boolean argNamesCountConsistent(Method m, String[] argNames) {
int pc = m.getParameterCount();
Class<?> first = pc > 0 ? m.getParameterTypes()[0] : null;
boolean implicitJp = first == org.aspectj.lang.JoinPoint.class
|| first == org.aspectj.lang.ProceedingJoinPoint.class
|| first == org.aspectj.lang.JoinPoint.StaticPart.class;
int expected = implicitJp ? pc - 1 : pc;
return argNames.length == expected || argNames.length == pc;
} Try / catch
try {
advice.getPointcut();
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("Expecting to find")) {
// reconcile arg-names length with the advice method signature
} else { throw ex; }
} Prevention
- Keep arg-names length in sync with the method parameter count (excluding the implicit joinpoint).
- Drop arg-names entirely when compiling with -parameters.
- Re-validate arg-names whenever the advice method signature changes.
When it happens
Trigger: Supplying arg-names with more or fewer entries than the method parameters (excluding the auto-inserted joinpoint slot), or parameter-name discovery returning a partial list. For example, a method after(JoinPoint jp, Object r) with arg-names="r" (missing the joinpoint slot) when the auto-insert logic at line 273 does not apply because counts do not line up to the +1 expectation.
Common situations: Mistyping the arg-names count in XML, refactoring the advice method signature (adding/removing a parameter) without updating arg-names, or a mismatch between the @Aspect method and the pointcut's bound variables. Also when debug-discovered names partially succeed.
Related errors
- 'argumentNames' property of AbstractAspectJAdvice contains…
- Not enough arguments in method to satisfy binding of…
- Advice method [ ] requires arguments to be bound by name…
- Advice must be declared inside an aspect type: Offending…
- is not an @AspectJ aspect
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/8b86c2d5f88ea47e.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:473
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
adviceParameterNameDiscoverer.setReturningName(this.returningName);
adviceParameterNameDiscoverer.setThrowingName(this.throwingName);
// Last in chain, so if we're called and we fail, that's bad...
adviceParameterNameDiscoverer.setRaiseExceptions(true);
discoverer.addDiscoverer(adviceParameterNameDiscoverer);
return discoverer;
}
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private void bindExplicitArguments(int numArgumentsLeftToBind) {
Assert.state(this.argumentNames != null, "No argument names available");
this.argumentBindings = new HashMap<>();
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();
if (this.argumentNames.length != numExpectedArgumentNames) {
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
" arguments to bind by name in advice, but actually found " +
this.argumentNames.length + " arguments.");
}
// So we match in number...
int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
this.argumentBindings.put(this.argumentNames[i], i);
}
// Check that returning and throwing were in the argument names list if
// specified, and find the discovered argument types.
if (this.returningName != null) {
if (!this.argumentBindings.containsKey(this.returningName)) {
throw new IllegalStateException("Returning argument name '" + this.returningName +
"' was not bound in advice arguments");
}
else {View on GitHub (pinned to 69bf83ad71)