spring-projects/spring-framework · error · IllegalStateException
Advice method [ ] requires arguments to be bound by name…
Error message
Advice method [{}] requires {} arguments to be bound by name, but the argument names were not specified and could not be discovered. What it means
Thrown by bindArgumentsByName (line 432-444) when the advice method has parameters that must be bound by name (numUnboundArgs > 0) but this.argumentNames is null — i.e. setArgumentNames was never called AND the ParameterNameDiscoverer chain returned null. The discoverer returns null when it cannot unambiguously deduce names (see AspectJAdviceParameterNameDiscoverer). Without names, pointcut parameter binding is impossible, so Spring fails fast.
Solutions
- Compile with -parameters (javac -parameters / Maven compiler-plugin <parameters>true</parameters>) so declared names are available to DefaultParameterNameDiscoverer.
- Explicitly specify arg-names in XML or use binding annotations so setArgumentNames is called.
- Rewrite the pointcut to use binding forms (args(x), this(x), @annotation(x)) that the discoverer can interpret.
- Reduce the number of unbound parameters so the heuristic algorithm can disambiguate.
Example fix
// before — advice compiled without -parameters; pointcut has no binding form
@AfterReturning("execution(* svc.*(..))")
public void after(Object retVal) { ... }
// after — bind via returning and compile with -parameters, OR name explicitly
@AfterReturning(pointcut="execution(* svc.*(..))", returning="retVal")
public void after(Object retVal) { ... }
// plus pom.xml: <maven.compiler.parameters>true</maven.compiler.parameters> Defensive patterns
Strategy: validation
Validate before calling
import org.springframework.core.DefaultParameterNameDiscoverer;
import java.lang.reflect.Method;
// Pre-check that parameter names are discoverable before registering advice.
boolean namesDiscoverable(Method adviceMethod) {
String[] names = new DefaultParameterNameDiscoverer().getParameterNames(adviceMethod);
return names != null;
}
// Build advice only when this returns true, else require explicit arg-names. Type guard
boolean hasBindableParameterNames(Method m, String[] explicitArgNames) {
if (explicitArgNames != null) return true;
return new org.springframework.core.DefaultParameterNameDiscoverer().getParameterNames(m) != null;
} Try / catch
try {
advice.getPointcut(); // triggers calculateArgumentBindings
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("could not be discovered")) {
// enable -parameters or supply arg-names, then retry
} else { throw ex; }
} Prevention
- Compile all modules containing @Aspect classes with -parameters (maven.compiler.parameters=true).
- Supply arg-names explicitly when parameter names may be unavailable.
- Prefer pointcut expressions with binding forms (args(), this(), @annotation()) so discovery can succeed.
When it happens
Trigger: An advice method with one or more non-joinpoint parameters, compiled WITHOUT -parameters (and without -debug variable info), whose pointcut expression does not unambiguously reveal the binding. For example @AfterReturning(pointcut="execution(* *(..))", returning="r") on a method after(Object r) compiled without parameter names. Also when the pointcut expression has no bindable forms (no args(), this(), target(), @annotation()) to deduce from.
Common situations: Java 8+ project not compiled with -parameters, obfuscated/stripped bytecode, advice with multiple unbound parameters that the heuristic algorithm cannot disambiguate, or a pointcut that uses no binding forms. Common when moving from annotation-style binding (where names came from debug info) to a stricter toolchain.
Related errors
- Failed to bind all argument names
- 'argumentNames' property of AbstractAspectJAdvice contains…
- Binding of throwing parameter
- Expecting to find arguments to bind by name in advice, but…
- Mismatch on arguments to advice method
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/c87802cf4fbf4333.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:441
if (JoinPoint.StaticPart.class == candidateParameterType) {
this.joinPointStaticPartArgumentIndex = 0;
return true;
}
else {
return false;
}
}
private void bindArgumentsByName(int numArgumentsExpectingToBind) {
if (this.argumentNames == null) {
this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
}
if (this.argumentNames != null) {
// We have been able to determine the arg names.
bindExplicitArguments(numArgumentsExpectingToBind);
}
else {
throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
"requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
"the argument names were not specified and could not be discovered.");
}
}
/**
* Create a ParameterNameDiscoverer to be used for argument binding.
* <p>The default implementation creates a {@link DefaultParameterNameDiscoverer}
* and adds a specifically configured {@link AspectJAdviceParameterNameDiscoverer}.
*/
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
// We need to discover them, or if that fails, guess,
// and if we can't guess with 100% accuracy, fail.
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
adviceParameterNameDiscoverer.setReturningName(this.returningName);
adviceParameterNameDiscoverer.setThrowingName(this.throwingName);View on GitHub (pinned to 69bf83ad71)