spring-projects/spring-framework · error · IllegalStateException
Required to bind arguments, but only bound (JoinPointMatch…
Error message
Required to bind {} arguments, but only bound {} (JoinPointMatch {} bound in invocation) What it means
Thrown by argBinding (line 602-606) at advice invocation time when the number of bound arguments (numBound) does not equal parameterTypes.length. numBound counts the joinpoint/static-part binding plus pointcut parameter bindings plus returning/throwing bindings. A shortfall means a parameter could not be populated — usually because the JoinPointMatch was null (pointcut did not actually match at runtime, so parameterBindings was empty) or because the pointcut bound fewer variables than the method expects.
Solutions
- Align the advice method's parameter count with the variables bound by the pointcut expression (args(), this(), target(), @annotation(), returning, throwing).
- If the message says 'JoinPointMatch was NOT bound', verify the pointcut actually matches the target method and that the proxy is correctly configured.
- Add explicit arg-names / use -parameters so Spring can match each parameter to a binding.
- Reduce the method to only the parameters you actually bind.
Example fix
// before — advice declares a param the pointcut does not bind
@After("execution(* svc.*(..)) && args(payload)")
public void after(JoinPoint jp, Object payload, Object extra) { ... } // extra unbound
// after — drop the unbindable parameter
@After("execution(* svc.*(..)) && args(payload)")
public void after(JoinPoint jp, Object payload) { ... } Defensive patterns
Strategy: validation
Validate before calling
import java.lang.reflect.Method;
// Sanity-check that the pointcut binds exactly as many variables as the advice needs.
// (Heuristic: count binding forms args/this/target/@annotation occurrences vs params minus joinpoint.)
int bindableParamCount(Method adviceMethod) {
int pc = adviceMethod.getParameterCount();
Class<?> first = pc > 0 ? adviceMethod.getParameterTypes()[0] : null;
boolean implicitJp = first == org.aspectj.lang.JoinPoint.class
|| first == org.aspectj.lang.ProceedingJoinPoint.class
|| first == org.aspectj.lang.JoinPoint.StaticPart.class;
return implicitJp ? pc - 1 : pc;
}
// Ensure your pointcut binds exactly this many variables. Type guard
boolean pointcutBindsEnoughVariables(String pointcutExpr, int paramsNeedingBinding) {
// crude count of binding forms; refine as needed
int forms = 0;
for (String kw : new String[]{"args(", "this(", "target(", "@annotation(", "@args(", "@this(", "@target("}) {
int idx = -1;
while ((idx = pointcutExpr.indexOf(kw, idx + 1)) >= 0) forms++;
}
return forms >= paramsNeedingBinding;
} Try / catch
// This fires at invocation time, not setup. Catch around the proxied call in integration tests:
try {
proxy.businessMethod();
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("Required to bind") && ex.getMessage().contains("only bound")) {
// reconcile pointcut bindings with advice parameters
} else { throw ex; }
} Prevention
- Make pointcut binding forms (args/this/target/@annotation) equal the non-joinpoint parameter count.
- Add integration tests that actually invoke the proxied method to surface this early.
- Avoid declaring advice parameters the pointcut does not bind.
When it happens
Trigger: An advice method declares more parameters than the pointcut expression binds, and the runtime JoinPointMatch is null (no bindings available). Also when a pointcut uses args(a,b) but the advice declares three parameters, or when the proxy somehow invokes advice without the matching context attached.
Common situations: Mismatch between pointcut binding variables and advice parameters, pointcut expression changed to bind fewer variables without updating the method, or running through a code path that does not attach the JoinPointMatch (e.g. manual invocation). The message distinguishes whether jpMatch was bound.
Related errors
- Mismatch on arguments to advice method
- Advice method [ ] requires arguments to be bound by name…
- 'argumentNames' property of AbstractAspectJAdvice contains…
- Binding of throwing parameter
- Expecting to find arguments to bind by name in advice, but…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/d3eacffee1a45620.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:603
}
// binding from returning clause
if (this.returningName != null) {
Integer index = this.argumentBindings.get(this.returningName);
Assert.state(index != null, "Index must not be null");
adviceInvocationArgs[index] = returnValue;
numBound++;
}
// binding from thrown exception
if (this.throwingName != null) {
Integer index = this.argumentBindings.get(this.throwingName);
Assert.state(index != null, "Index must not be null");
adviceInvocationArgs[index] = ex;
numBound++;
}
}
if (numBound != this.parameterTypes.length) {
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
" arguments, but only bound " + numBound + " (JoinPointMatch " +
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
}
return adviceInvocationArgs;
}
/**
* Invoke the advice method.
* @param jpMatch the JoinPointMatch that matched this execution join point
* @param returnValue the return value from the method execution (may be null)
* @param ex the exception thrown by the method execution (may be null)
* @return the invocation result
* @throws Throwable in case of invocation failure
*/
protected @Nullable Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch,
@Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {View on GitHub (pinned to 69bf83ad71)