{"id":"5b1486a97361f877","repo":"spring-projects/spring-framework","slug":"found-candidate-reference-pointcut-variables-bu","errorCode":null,"errorMessage":"Found {} candidate reference pointcut variables but only one unbound argument slot","messagePattern":"Found (.+?) candidate reference pointcut variables but only one unbound argument slot","errorType":"exception","errorClass":"AmbiguousBindingException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java","lineNumber":577,"sourceCode":"\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// eat the body\n\t\t\tPointcutBody body = getPointcutBody(tokens, i);\n\t\t\ti += body.numTokensConsumed;\n\n\t\t\tif (!nonReferencePointcutTokens.contains(toMatch)) {\n\t\t\t\t// then it could be a reference pointcut\n\t\t\t\tString varName = maybeExtractVariableName(body.text);\n\t\t\t\tif (varName != null) {\n\t\t\t\t\tvarNames.add(varName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (varNames.size() > 1) {\n\t\t\tthrow new AmbiguousBindingException(\"Found \" + varNames.size() +\n\t\t\t\t\t\" candidate reference pointcut variables but only one unbound argument slot\");\n\t\t}\n\t\telse if (varNames.size() == 1) {\n\t\t\tfor (int j = 0; j < this.parameterNameBindings.length; j++) {\n\t\t\t\tif (isUnbound(j)) {\n\t\t\t\t\tbindParameterName(j, varNames.get(0));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// else varNames.size must be 0 and we have nothing to bind.\n\t}\n\n\t/**\n\t * We've found the start of a binding pointcut at the given index into the\n\t * token array. Now we need to extract the pointcut body and return it.\n\t */\n\tprivate PointcutBody getPointcutBody(String[] tokens, int startIndex) {","sourceCodeStart":559,"sourceCodeEnd":595,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L559-L595","documentation":"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.","triggerScenarios":"A pointcut referencing multiple named pointcuts each containing a binding variable, while only one parameter is unbound.","commonSituations":"Composing several reusable pointcuts that each bind a variable but the advice consumes only one; refactor leaving an extra binding clause.","solutions":["Align the number of reference-pointcut binding variables with the unbound parameter count.","Remove extra reference pointcut bindings from the composed expression.","Compile with -parameters and ensure each bound variable has a corresponding parameter."],"exampleFix":"// before\n@Before(\"serviceOps() && webOps()\")\npublic void before(Object req) { ... }\n// where both named pointcuts bind a variable\n\n// after\n@Before(\"serviceOps()\")\npublic void before(Object req) { ... }","handlingStrategy":"validation","validationCode":"// Limit reference-pointcut binding variables to one when only one slot is unbound:\nint refVars = countReferencePointcutBindingVars(pointcutExpression);\nassert refVars <= 1;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compose reference pointcuts so at most one binds a variable per advice.","Compile with -parameters.","Review composed pointcut expressions after refactor."],"tags":["spring-aop","aspectj","advice-binding","reference-pointcut"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}