spring-projects/spring-framework · error · AmbiguousBindingException
Binding of returning parameter '{}' is ambiguous: there are
Error message
Binding of returning parameter '{}' is ambiguous: there are {} candidates. Consider compiling with -parameters in order to make declared parameter names available. What it means
Thrown by AspectJAdviceParameterNameDiscoverer when a 'returning' name was specified on an @AfterReturning advice but more than one advice-method parameter remains unbound at the returning-binding stage. Spring cannot decide which of the multiple candidate parameters the return value should bind to, because parameter names were not compiled in (-parameters flag absent). Only surfaces when raiseExceptions=true; otherwise the discoverer returns null and the failure is logged.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:370
"' could not be completed as no available arguments are a subtype of Throwable");
}
else {
bindParameterName(throwableIndex, this.throwingName);
}
}
/**
* If a returning variable was specified and there is only one choice remaining, bind it.
*/
private void maybeBindReturningVariable() {
if (this.numberOfRemainingUnboundArguments == 0) {
throw new IllegalStateException(
"Algorithm assumes that there must be at least one unbound parameter on entry to this method");
}
if (this.returningName != null) {
if (this.numberOfRemainingUnboundArguments > 1) {
throw new AmbiguousBindingException("Binding of returning parameter '" + this.returningName +
"' is ambiguous: there are " + this.numberOfRemainingUnboundArguments + " candidates. " +
"Consider compiling with -parameters in order to make declared parameter names available.");
}
// We're all set... find the unbound parameter, and bind it.
for (int i = 0; i < this.parameterNameBindings.length; i++) {
if (this.parameterNameBindings[i] == null) {
bindParameterName(i, this.returningName);
break;
}
}
}
}
/**
* Parse the string pointcut expression looking for:
* @this, @target, @args, @within, @withincode, @annotation.
* If we find one of these pointcut expressions, try and extract a candidate variableView on GitHub (pinned to e8729d0438)
Solutions
- Compile with javac -parameters (or <parameters>true</parameters> in maven-compiler-plugin / compilerArgs in Gradle) so real parameter names are available.
- Reduce the advice method to exactly one unbound parameter at the returning stage by adding explicit pointcut binding (this/target/args/annotation) for the other parameters.
- Remove the extra parameters from the advice signature that are not actually needed.
- If using @AfterReturning, ensure the returning attribute type matches exactly one parameter.
Example fix
// before
@AfterReturning(pointcut="execution(* com.acme.*.*(..))", returning="ret")
public void after(Object ret, Object extra) { ... }
// after
@AfterReturning(pointcut="execution(* com.acme.*.*(..))", returning="ret")
public void after(Object ret) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Compile with -parameters; verify before deploying: // javac -parameters ... // or in advice, keep exactly one unbound param at the returning stage.
Prevention
- Always compile with -parameters in any project using Spring AOP advice binding.
- Keep @AfterReturning advice methods to the minimum parameters needed.
- Enable raiseExceptions=true only in tests to surface binding ambiguity early.
When it happens
Trigger: An @AfterReturning advice method with multiple untyped/unbound parameters (e.g. two Objects) combined with returning="someName", where the pointcut expression and prior binding stages (JoinPoint, throwing, annotation) did not resolve enough parameters to leave exactly one unbound slot.
Common situations: Advice methods written with several parameters that are not named in bytecode; migrating from ajc-compiled aspects (which embed parameter names) to javac-compiled ones; upgrading Spring versions where stricter binding checks were added.
Related errors
- Still {} unbound args at this()/target()/args() binding stag
- MethodInvocation is not a Spring ProxyMethodInvocation: {}
- 'argumentNames' property of AbstractAspectJAdvice contains a
- Only afterReturning advice can be used to bind a return valu
- Only afterThrowing advice can be used to bind a thrown excep
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/eb95bfafd84b5086.json.
Report an issue: GitHub.