spring-projects/spring-framework · error · IllegalStateException
Binding of throwing parameter
Error message
Binding of throwing parameter '{}' could not be completed as no available arguments are a subtype of Throwable What it means
Thrown by maybeBindThrowingVariable (line 350-353) when a throwingName is set but NONE of the unbound advice parameters is a subtype of Throwable. After-throwing advice binds the thrown exception to a parameter; if no parameter can hold a Throwable, binding is impossible. Raised as IllegalStateException (suppressed unless raiseExceptions, but AbstractAspectJAdvice sets raiseExceptions=true at line 461).
Solutions
- Declare at least one advice parameter whose type is a Throwable subtype (e.g. Throwable, RuntimeException, or the specific exception).
- Ensure the throwing name matches that parameter (or compile with -parameters).
- If the method needs non-exception context too, add the Throwable parameter alongside it.
Example fix
// before — no Throwable parameter to bind the thrown exception
@AfterThrowing(pointcut="execution(* svc.*(..))", throwing="ex")
public void onError(String message) { ... }
// after — add a Throwable-typed parameter
@AfterThrowing(pointcut="execution(* svc.*(..))", throwing="ex")
public void onError(Throwable ex) { ... } Defensive patterns
Strategy: validation
Validate before calling
import java.lang.reflect.Method;
// Ensure at least one Throwable parameter exists before setting throwing.
void assertHasThrowableParam(Method adviceMethod) {
for (Class<?> t : adviceMethod.getParameterTypes()) {
if (Throwable.class.isAssignableFrom(t)) return;
}
throw new IllegalStateException("after-throwing advice needs a Throwable-typed parameter");
} Type guard
boolean hasThrowableParam(Method m) {
for (Class<?> t : m.getParameterTypes()) {
if (Throwable.class.isAssignableFrom(t)) return true;
}
return false;
} Try / catch
try {
advice.getPointcut();
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("no available arguments are a subtype of Throwable")) {
// add a Throwable-typed parameter to the advice method
} else { throw ex; }
} Prevention
- Always declare a Throwable (or subtype) parameter on after-throwing advice.
- When converting after-returning to after-throwing, change the parameter type.
- Validate the advice signature against the throwing attribute at startup.
When it happens
Trigger: An after-throwing advice declares throwing="ex" but its parameters are all non-Throwable (e.g. after(String msg, Integer code)). Or the only Throwable parameter was already bound to something else (e.g. JoinPoint consumed the slot).
Common situations: Declaring an after-throwing advice without a Throwable-typed parameter, or binding the wrong parameter type. Common when converting an after-returning advice to after-throwing and forgetting to change the parameter type, or when the throwing attribute is set but the method signature lacks an exception parameter.
Related errors
- Binding of throwing parameter
- Failed to bind all argument names
- Not enough arguments in method to satisfy binding of…
- Throwing argument name
- Throwing name ' ' is neither a valid argument name nor the…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/a6cc4a4354a15f26.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:351
// 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.
*/
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) {View on GitHub (pinned to 69bf83ad71)