{"id":"b3ca9e7cbf419c6b","repo":"spring-projects/spring-framework","slug":"found-potential-annotation-variable-s-and-p","errorCode":null,"errorMessage":"Found {} potential annotation variable(s) and {} potential argument slots","messagePattern":"Found (.+?) potential annotation variable\\(s\\) and (.+?) potential argument slots","errorType":"exception","errorClass":"AmbiguousBindingException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java","lineNumber":427,"sourceCode":"\t\t\telse if (tokens[i].startsWith(\"@args(\") || tokens[i].equals(\"@args\")) {\n\t\t\t\tPointcutBody body = getPointcutBody(tokens, i);\n\t\t\t\ti += body.numTokensConsumed;\n\t\t\t\tmaybeExtractVariableNamesFromArgs(body.text, varNames);\n\t\t\t}\n\t\t}\n\n\t\tbindAnnotationsFromVarNames(varNames);\n\t}\n\n\t/**\n\t * Match the given list of extracted variable names to argument slots.\n\t */\n\tprivate void bindAnnotationsFromVarNames(List<String> varNames) {\n\t\tif (!varNames.isEmpty()) {\n\t\t\t// we have work to do...\n\t\t\tint numAnnotationSlots = countNumberOfUnboundAnnotationArguments();\n\t\t\tif (numAnnotationSlots > 1) {\n\t\t\t\tthrow new AmbiguousBindingException(\"Found \" + varNames.size() +\n\t\t\t\t\t\t\" potential annotation variable(s) and \" +\n\t\t\t\t\t\tnumAnnotationSlots + \" potential argument slots\");\n\t\t\t}\n\t\t\telse if (numAnnotationSlots == 1) {\n\t\t\t\tif (varNames.size() == 1) {\n\t\t\t\t\t// it's a match\n\t\t\t\t\tfindAndBind(Annotation.class, varNames.get(0));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// multiple candidate vars, but only one slot\n\t\t\t\t\tthrow new IllegalArgumentException(\"Found \" + varNames.size() +\n\t\t\t\t\t\t\t\" candidate annotation binding variables\" +\n\t\t\t\t\t\t\t\" but only one potential argument binding slot\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// no slots so presume those candidate vars were actually type names\n\t\t\t}","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L409-L445","documentation":"Thrown during the annotation-binding stage when the pointcut expression yields candidate annotation variable names AND there is more than one unbound Annotation-typed argument slot in the advice method. Spring cannot map the extracted names to slots unambiguously. Only thrown when raiseExceptions=true; otherwise null is returned.","triggerScenarios":"A pointcut using binding forms of @annotation/@this/@target/@args/@within/@withincode with more than one Annotation-typed parameter left unbound in the advice method signature.","commonSituations":"Writing an advice that observes multiple annotations at once without compiled parameter names; combining @args (which can produce multiple binding names) with several Annotation parameters.","solutions":["Compile with -parameters so declared names disambiguate bindings.","Ensure there is at most one unbound Annotation-typed parameter when the pointcut contains annotation binding primitives, or match each annotation parameter explicitly in the pointcut.","Split the advice into multiple advices each binding a single annotation."],"exampleFix":"// before\n@Before(\"@annotation(audit) && @annotation(sec)\")\npublic void check(Audit audit, Security sec) { ... }\n\n// after\n@Before(\"@annotation(audit) && @annotation(sec)\")\npublic void check(Audit audit, Security sec) { ... }\n// and compile with -parameters, OR use two separate @Before methods each binding one annotation","handlingStrategy":"validation","validationCode":"// Ensure at most one unbound Annotation-typed param when pointcut has annotation bindings:\nlong unboundAnnotationParams = Arrays.stream(method.getParameterTypes())\n    .filter(p -> Annotation.class.isAssignableFrom(p))\n    .count();\nassert unboundAnnotationParams <= 1;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compile with -parameters.","Keep annotation-binding advice methods to a single Annotation parameter, or one per @annotation clause.","Use ajc which embeds parameter names if javac -parameters is not an option."],"tags":["spring-aop","aspectj","advice-binding","annotation"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}