spring-projects/spring-framework · error · AmbiguousBindingException

Found {} candidate reference pointcut variables but only one

Error message

Found {} candidate reference pointcut variables but only one unbound argument slot

What it means

Thrown when multiple candidate variable names are extracted from reference pointcuts in the expression but only one unbound argument slot remains. Spring cannot choose which name to bind. Only surfaces when raiseExceptions=true.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:577

				}

			}

			// eat the body
			PointcutBody body = getPointcutBody(tokens, i);
			i += body.numTokensConsumed;

			if (!nonReferencePointcutTokens.contains(toMatch)) {
				// then it could be a reference pointcut
				String varName = maybeExtractVariableName(body.text);
				if (varName != null) {
					varNames.add(varName);
				}
			}
		}

		if (varNames.size() > 1) {
			throw new AmbiguousBindingException("Found " + varNames.size() +
					" candidate reference pointcut 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.
	}

	/**
	 * We've found the start of a binding pointcut at the given index into the
	 * token array. Now we need to extract the pointcut body and return it.
	 */
	private PointcutBody getPointcutBody(String[] tokens, int startIndex) {

View on GitHub (pinned to e8729d0438)

Solutions

  1. Align the number of reference-pointcut binding variables with the unbound parameter count.
  2. Remove extra reference pointcut bindings from the composed expression.
  3. Compile with -parameters and ensure each bound variable has a corresponding parameter.

Example fix

// before
@Before("serviceOps() && webOps()")
public void before(Object req) { ... }
// where both named pointcuts bind a variable

// after
@Before("serviceOps()")
public void before(Object req) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Limit reference-pointcut binding variables to one when only one slot is unbound:
int refVars = countReferencePointcutBindingVars(pointcutExpression);
assert refVars <= 1;

Prevention

When it happens

Trigger: A pointcut referencing multiple named pointcuts each containing a binding variable, while only one parameter is unbound.

Common situations: Composing several reusable pointcuts that each bind a variable but the advice consumes only one; refactor leaving an extra binding clause.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/5b1486a97361f877.json. Report an issue: GitHub.