{"id":"3d08ce60bf228d77","repo":"spring-projects/spring-framework","slug":"still-unbound-args-at-reference-pointcut-bindin","errorCode":null,"errorMessage":"Still {} unbound args at reference pointcut binding stage, with no way to determine between them","messagePattern":"Still (.+?) unbound args at reference pointcut binding stage, with no way to determine between them","errorType":"exception","errorClass":"AmbiguousBindingException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java","lineNumber":533,"sourceCode":"\n\t\tif (varNames.size() > 1) {\n\t\t\tthrow new AmbiguousBindingException(\"Found \" + varNames.size() +\n\t\t\t\t\t\" candidate this(), target(), or args() 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\tprivate void maybeBindReferencePointcutParameter() {\n\t\tif (this.numberOfRemainingUnboundArguments > 1) {\n\t\t\tthrow new AmbiguousBindingException(\"Still \" + this.numberOfRemainingUnboundArguments +\n\t\t\t\t\t\" unbound args at reference pointcut binding stage, with no way to determine between them\");\n\t\t}\n\n\t\tList<String> varNames = new ArrayList<>();\n\t\tString[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, \" \");\n\t\tfor (int i = 0; i < tokens.length; i++) {\n\t\t\tString toMatch = tokens[i];\n\t\t\tif (toMatch.startsWith(\"!\")) {\n\t\t\t\ttoMatch = toMatch.substring(1);\n\t\t\t}\n\t\t\tint firstParenIndex = toMatch.indexOf('(');\n\t\t\tif (firstParenIndex != -1) {\n\t\t\t\ttoMatch = toMatch.substring(0, firstParenIndex);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (tokens.length < i + 2) {\n\t\t\t\t\t// no \"(\" and nothing following\n\t\t\t\t\tcontinue;","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L515-L551","documentation":"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.","triggerScenarios":"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.","commonSituations":"Complex pointcut compositions referencing named pointcuts with multiple unbound advice parameters; missing -parameters flag.","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."],"exampleFix":"// before\n@Pointcut(\"execution(* com.acme.*.*(..))\")\npublic void pc() {}\n@Before(\"pc() && args(val)\")\npublic void before(Object val, Object extra) { ... }\n\n// after\n@Before(\"pc() && args(val)\")\npublic void before(Object val) { ... }","handlingStrategy":"validation","validationCode":"// Ensure at most one unbound param when relying on reference pointcut binding; else compile -parameters.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compile with -parameters.","Bind extra params via earlier stages so only one reaches the reference-pointcut stage.","Minimize advice parameter count."],"tags":["spring-aop","aspectj","advice-binding","reference-pointcut"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}