{"record":{"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/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L409-L445","documentation":"Thrown by AspectJAdviceParameterNameDiscoverer during annotation-based pointcut binding. The pointcut expression uses annotation-binding designators (@annotation, @this, @target, @within, @withincode, @args in binding form) but the advice method has more than one unbound parameter that is a subtype of Annotation. Spring cannot match which annotation parameter corresponds to which binding.","triggerScenarios":"An advice method with two or more annotation-typed parameters and a pointcut that uses annotation-binding designators — e.g. @Before(\"@annotation(a)\") void before(MyAnnotation a, OtherAnnotation b) where both are unbound annotation-typed params. Only fires when setRaiseExceptions(true).","commonSituations":"Multiple annotation bindings in a single pointcut combined with multiple annotation-typed advice parameters, compiled without -parameters.","solutions":["Compile with -parameters so actual parameter names resolve directly without deduction","Restrict the advice method to a single annotation-typed parameter per binding","Split the advice into separate advice methods, each handling one annotation binding"],"exampleFix":"// before\n@Before(\"@annotation(a)\")\npublic void before(MyAnnotation a, OtherAnnotation b) { ... } // 2 annotation slots, ambiguous\n\n// after\n@Before(\"@annotation(a)\")\npublic void before(MyAnnotation a) { ... }","handlingStrategy":"validation","validationCode":"// Count annotation-typed unbound parameters and warn if >1 with annotation bindings\nlong annotationParams = Arrays.stream(adviceMethod.getParameterTypes())\n    .filter(p -> p != JoinPoint.class && p != ProceedingJoinPoint.class)\n    .filter(Annotation.class::isAssignableFrom)\n    .count();\nif (annotationParams > 1 && pointcutExpr.contains(\"@annotation\") || pointcutExpr.contains(\"@args\")) {\n    throw new IllegalStateException(\"Multiple annotation-typed params with annotation bindings are ambiguous\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    discoverer.getParameterNames(adviceMethod);\n} catch (AspectJAdviceParameterNameDiscoverer.AmbiguousBindingException ex) {\n    // Reduce to one annotation param or split into separate advice methods\n}","preventionTips":["Compile with -parameters","Use at most one annotation-typed parameter per advice method when relying on @annotation/@this/@target/@within/@args bindings"],"tags":["spring-aop","aspectj","annotation-binding","parameter-binding"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}