spring-projects/spring-framework · error · AmbiguousBindingException
Still {} unbound args at reference pointcut binding stage, w
Error message
Still {} unbound args at reference pointcut binding stage, with no way to determine between them What it means
Thrown at the reference-pointcut binding stage when more than one parameter is still unbound. A reference pointcut (a named pointcut referenced by name) can supply at most one binding variable, so multiple unbound slots make binding impossible. Only surfaces when raiseExceptions=true.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:533
if (varNames.size() > 1) {
throw new AmbiguousBindingException("Found " + varNames.size() +
" candidate this(), target(), or args() variables but only one unbound argument slot");
}
else if (varNames.size() == 1) {
for (int j = 0; j < this.parameterNameBindings.length; j++) {
if (isUnbound(j)) {
bindParameterName(j, varNames.get(0));
break;
}
}
}
// else varNames.size must be 0 and we have nothing to bind.
}
private void maybeBindReferencePointcutParameter() {
if (this.numberOfRemainingUnboundArguments > 1) {
throw new AmbiguousBindingException("Still " + this.numberOfRemainingUnboundArguments +
" unbound args at reference pointcut binding stage, with no way to determine between them");
}
List<String> varNames = new ArrayList<>();
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
for (int i = 0; i < tokens.length; i++) {
String toMatch = tokens[i];
if (toMatch.startsWith("!")) {
toMatch = toMatch.substring(1);
}
int firstParenIndex = toMatch.indexOf('(');
if (firstParenIndex != -1) {
toMatch = toMatch.substring(0, firstParenIndex);
}
else {
if (tokens.length < i + 2) {
// no "(" and nothing following
continue;View on GitHub (pinned to e8729d0438)
Solutions
- Compile with -parameters so earlier stages resolve parameters and fewer reach this stage.
- Bind remaining parameters via returning/throwing/annotation/args so at most one is left.
- Reduce the advice method parameter count.
Example fix
// before
@Pointcut("execution(* com.acme.*.*(..))")
public void pc() {}
@Before("pc() && args(val)")
public void before(Object val, Object extra) { ... }
// after
@Before("pc() && args(val)")
public void before(Object val) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Ensure at most one unbound param when relying on reference pointcut binding; else compile -parameters.
Prevention
- Compile with -parameters.
- Bind extra params via earlier stages so only one reaches the reference-pointcut stage.
- Minimize advice parameter count.
When it happens
Trigger: An advice method with two or more unbound parameters reaches the final reference-pointcut binding stage, and the referenced pointcut body yields a candidate variable name.
Common situations: Complex pointcut compositions referencing named pointcuts with multiple unbound advice parameters; missing -parameters flag.
Related errors
- Found {} candidate reference pointcut variables but only one
- Binding of returning parameter '{}' is ambiguous: there are
- Found {} potential annotation variable(s) and {} potential a
- Found {} candidate annotation binding variables but only one
- Still {} unbound args at this()/target()/args() binding stag
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/3d08ce60bf228d77.json.
Report an issue: GitHub.