{"record":{"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/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L559-L595","documentation":"Thrown when one unbound argument slot remains but the pointcut's reference pointcut expressions yield multiple candidate variable names. Spring cannot choose among the candidates for the single slot.","triggerScenarios":"A pointcut referencing multiple shared named pointcuts that each expose a binding variable, with an advice method that has exactly one unbound slot — e.g. @Before(\"com.x.Pc1.a(p1) && com.x.Pc2.b(p2)\") void before(Object single). Only fires when setRaiseExceptions(true).","commonSituations":"Composed pointcut references with multiple exposed bindings but a single advice parameter, compiled without -parameters.","solutions":["Compile with -parameters to resolve names directly","Reduce the pointcut to a single reference-pointcut binding or add a parameter for each","Restructure the pointcut composition to expose only one binding variable"],"exampleFix":"// before\n@Before(\"com.x.Pc1.first(p1) && com.x.Pc2.second(p2)\")\npublic void before(Object single) { ... } // 2 candidates, 1 slot\n\n// after\n@Before(\"com.x.Pc1.first(p1)\")\npublic void before(Object p1) { ... }","handlingStrategy":"validation","validationCode":"// If using reference pointcuts that expose bindings, ensure at most one binding variable per unbound slot\n// Reference pointcuts are named pointcuts referenced in the expression (not AspectJ keywords).\n// Compiling with -parameters makes this check unnecessary.","typeGuard":null,"tryCatchPattern":"try {\n    discoverer.getParameterNames(adviceMethod);\n} catch (AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException ex) {\n    // Reduce reference pointcut bindings to one, or add params for each\n}","preventionTips":["Compile with -parameters","Expose at most one binding variable from reference pointcuts when the advice has a single unbound param"],"tags":["spring-aop","aspectj","reference-pointcut","parameter-binding"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}