spring-projects/spring-framework · error · AmbiguousBindingException
Binding of throwing parameter '{}' is ambiguous: could be bo
Error message
Binding of throwing parameter '{}' is ambiguous: could be bound to argument {} or {} What it means
Thrown by maybeBindThrowingVariable (line 342-346) as an AmbiguousBindingException when throwingName is set and there are two or more unbound advice parameters that are subtypes of Throwable. The heuristic cannot decide which one binds the thrown exception, so it refuses rather than guess.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:343
/**
* If a throwing name was specified and there is exactly one choice remaining
* (argument that is a subtype of Throwable) then bind it.
*/
private void maybeBindThrowingVariable() {
if (this.throwingName == null) {
return;
}
// So there is binding work to do...
int throwableIndex = -1;
for (int i = 0; i < this.argumentTypes.length; i++) {
if (isUnbound(i) && isSubtypeOf(Throwable.class, i)) {
if (throwableIndex == -1) {
throwableIndex = i;
}
else {
// Second candidate we've found - ambiguous binding
throw new AmbiguousBindingException("Binding of throwing parameter '" +
this.throwingName + "' is ambiguous: could be bound to argument " +
throwableIndex + " or " + i);
}
}
}
if (throwableIndex == -1) {
throw new IllegalStateException("Binding of throwing parameter '" + this.throwingName +
"' 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.
*/View on GitHub (pinned to e8729d0438)
Solutions
- Compile with -parameters so the discoverer binds by the actual parameter name matching the throwing attribute.
- Supply explicit arg-names so the throwing name maps to the intended parameter.
- Reduce the advice method to a single Throwable-typed parameter.
Example fix
// before
@AfterThrowing(value = "...", throwing = "ex")
public void onThrow(RuntimeException ex, Exception ctx) { ... } // compiled w/o -parameters
// after
@AfterThrowing(value = "...", throwing = "ex", argNames = "ex,ctx")
public void onThrow(RuntimeException ex, Exception ctx) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Before wiring after-throwing, ensure at most one unbound Throwable param unless names are known.
long throwableParams = Arrays.stream(adviceMethod.getParameterTypes())
.filter(Throwable.class::isAssignableFrom).count();
boolean namesAvailable = new DefaultParameterNameDiscoverer().getParameterNames(adviceMethod) != null;
if (throwingName != null && throwableParams > 1 && !namesAvailable) {
throw new IllegalStateException("Ambiguous throwing binding on " + adviceMethod
+ " — supply arg-names or compile with -parameters");
} Prevention
- Compile aspects with -parameters so throwing binds by name, not by type.
- Supply explicit arg-names when multiple Throwable-typed parameters exist.
- Prefer a single exception-typed parameter per after-throwing advice.
When it happens
Trigger: An after-throwing advice method declares multiple Throwable subtypes (e.g. RuntimeException and Exception) and throwing='ex' is set, while parameter names aren't available (compiled without -parameters) so the discoverer falls back to type-based matching and finds multiple candidates.
Common situations: Advice methods with more than one exception-typed parameter; mixing a generic Throwable param with a specific exception type; bytecode without parameter names forcing type-based binding.
Related errors
- Only afterThrowing advice can be used to bind a thrown excep
- Throwing name '{}' is neither a valid argument name nor the
- Advice method [{}] requires {} arguments to be bound by name
- Throwing argument name '{}' was not bound in advice argument
- Failed to bind all argument names: {} argument(s) could not
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/f4128ccd26861112.json.
Report an issue: GitHub.