spring-projects/spring-framework · error · AmbiguousBindingException
Found {} candidate this(), target(), or args() variables but
Error message
Found {} candidate this(), target(), or args() variables but only one unbound argument slot What it means
Thrown when the pointcut expression contains multiple candidate this/target/args binding variables but there is only one unbound argument slot. Spring cannot decide which variable name to bind. Only surfaces when raiseExceptions=true.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:517
}
}
else if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
PointcutBody body = getPointcutBody(tokens, i);
i += body.numTokensConsumed;
List<String> candidateVarNames = new ArrayList<>();
maybeExtractVariableNamesFromArgs(body.text, candidateVarNames);
// we may have found some var names that were bound in previous primitive args binding step,
// filter them out...
for (String varName : candidateVarNames) {
if (!alreadyBound(varName)) {
varNames.add(varName);
}
}
}
}
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");
}View on GitHub (pinned to e8729d0438)
Solutions
- Make the advice method parameter count match the number of bound variables in the pointcut.
- Remove extra this/target/args binding clauses from the pointcut.
- Compile with -parameters and ensure each bound variable has a corresponding parameter.
Example fix
// before
@Before("target(t) && args(a)")
public void before(Object t) { ... }
// after
@Before("target(t) && args(a)")
public void before(Object t, Object a) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Match this/target/args binding var count to unbound param count: int vars = extractBindingVars(this_target_args, pointcutExpression).size(); int unbound = countUnboundParams(adviceMethod); assert vars <= unbound && (vars == 0 || unbound == 1);
Prevention
- Keep this()/target()/args() binding variable count equal to the number of corresponding advice parameters.
- Compile with -parameters.
- Avoid binding the same variable twice across clauses.
When it happens
Trigger: A pointcut like 'target(t) && args(a, b)' yielding two candidate names while only one parameter remains unbound at this stage.
Common situations: Pointcuts that bind multiple variables via this/target/args but the advice method has fewer corresponding parameters; refactor mismatches.
Related errors
- 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
- Still {} unbound args at reference pointcut binding stage, w
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/1e929e7797f0e265.json.
Report an issue: GitHub.