{"record":{"id":"8b86c2d5f88ea47e","repo":"spring-projects/spring-framework","slug":"expecting-to-find-arguments-to-bind-by-name-in","errorCode":null,"errorMessage":"Expecting to find {} arguments to bind by name in advice, but actually found {} arguments.","messagePattern":"Expecting to find (.+?) arguments to bind by name in advice, but actually found (.+?) arguments\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":473,"sourceCode":"\t\tDefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();\n\t\tAspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =\n\t\t\t\tnew AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());\n\t\tadviceParameterNameDiscoverer.setReturningName(this.returningName);\n\t\tadviceParameterNameDiscoverer.setThrowingName(this.throwingName);\n\t\t// Last in chain, so if we're called and we fail, that's bad...\n\t\tadviceParameterNameDiscoverer.setRaiseExceptions(true);\n\t\tdiscoverer.addDiscoverer(adviceParameterNameDiscoverer);\n\t\treturn discoverer;\n\t}\n\n\t@SuppressWarnings(\"NullAway\") // Dataflow analysis limitation\n\tprivate void bindExplicitArguments(int numArgumentsLeftToBind) {\n\t\tAssert.state(this.argumentNames != null, \"No argument names available\");\n\t\tthis.argumentBindings = new HashMap<>();\n\n\t\tint numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();\n\t\tif (this.argumentNames.length != numExpectedArgumentNames) {\n\t\t\tthrow new IllegalStateException(\"Expecting to find \" + numExpectedArgumentNames +\n\t\t\t\t\t\" arguments to bind by name in advice, but actually found \" +\n\t\t\t\t\tthis.argumentNames.length + \" arguments.\");\n\t\t}\n\n\t\t// So we match in number...\n\t\tint argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;\n\t\tfor (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {\n\t\t\tthis.argumentBindings.put(this.argumentNames[i], i);\n\t\t}\n\n\t\t// Check that returning and throwing were in the argument names list if\n\t\t// specified, and find the discovered argument types.\n\t\tif (this.returningName != null) {\n\t\t\tif (!this.argumentBindings.containsKey(this.returningName)) {\n\t\t\t\tthrow new IllegalStateException(\"Returning argument name '\" + this.returningName +\n\t\t\t\t\t\t\"' was not bound in advice arguments\");\n\t\t\t}\n\t\t\telse {","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L455-L491","documentation":"Thrown by bindExplicitArguments (line 471-476) when the length of the resolved argumentNames array does not equal the advice method's parameter count. Spring requires an exact 1:1 correspondence because each parameter is mapped by index to a pointcut binding. A mismatch indicates the supplied arg-names or discovered names describe a different signature than the method.","triggerScenarios":"Supplying arg-names with more or fewer entries than the method parameters (excluding the auto-inserted joinpoint slot), or parameter-name discovery returning a partial list. For example, a method after(JoinPoint jp, Object r) with arg-names=\"r\" (missing the joinpoint slot) when the auto-insert logic at line 273 does not apply because counts do not line up to the +1 expectation.","commonSituations":"Mistyping the arg-names count in XML, refactoring the advice method signature (adding/removing a parameter) without updating arg-names, or a mismatch between the @Aspect method and the pointcut's bound variables. Also when debug-discovered names partially succeed.","solutions":["Make the arg-names list length equal the method parameter count (Spring auto-inserts the joinpoint slot only when argNames.length == paramCount - 1, see line 273).","After changing an advice method signature, update arg-names to match.","If using -parameters, remove arg-names entirely and let Spring discover them.","Verify the pointcut binds exactly the variables named in arg-names."],"exampleFix":"// before — arg-names count != method params (method has 2 params, names has 1)\n<aop:after-returning method=\"after\"\n    pointcut=\"execution(* *(..)) && args(payload)\"\n    arg-names=\"payload\" returning=\"ret\"/>\npublic void after(JoinPoint jp, Object ret) {} // jp is implicit; needs ret too\n\n// after — include all non-implicit names, or drop arg-names and compile with -parameters\n<aop:after-returning method=\"after\"\n    pointcut=\"execution(* *(..)) && args(payload)\"\n    returning=\"ret\"/>\npublic void after(JoinPoint jp, Object payload, Object ret) {}","handlingStrategy":"validation","validationCode":"import java.lang.reflect.Method;\n\n// Ensure arg-names count matches the method parameter count (accounting for the implicit joinpoint slot).\nvoid assertArgNamesCount(Method adviceMethod, String[] argNames) {\n    int pc = adviceMethod.getParameterCount();\n    Class<?> first = pc > 0 ? adviceMethod.getParameterTypes()[0] : null;\n    boolean hasImplicitJp = first == org.aspectj.lang.JoinPoint.class\n            || first == org.aspectj.lang.ProceedingJoinPoint.class\n            || first == org.aspectj.lang.JoinPoint.StaticPart.class;\n    int expected = hasImplicitJp ? pc - 1 : pc;\n    if (argNames.length != expected && argNames.length != pc) {\n        throw new IllegalStateException(\"arg-names count \" + argNames.length + \" != params \" + expected);\n    }\n}","typeGuard":"boolean argNamesCountConsistent(Method m, String[] argNames) {\n    int pc = m.getParameterCount();\n    Class<?> first = pc > 0 ? m.getParameterTypes()[0] : null;\n    boolean implicitJp = first == org.aspectj.lang.JoinPoint.class\n            || first == org.aspectj.lang.ProceedingJoinPoint.class\n            || first == org.aspectj.lang.JoinPoint.StaticPart.class;\n    int expected = implicitJp ? pc - 1 : pc;\n    return argNames.length == expected || argNames.length == pc;\n}","tryCatchPattern":"try {\n    advice.getPointcut();\n} catch (IllegalStateException ex) {\n    if (ex.getMessage().contains(\"Expecting to find\")) {\n        // reconcile arg-names length with the advice method signature\n    } else { throw ex; }\n}","preventionTips":["Keep arg-names length in sync with the method parameter count (excluding the implicit joinpoint).","Drop arg-names entirely when compiling with -parameters.","Re-validate arg-names whenever the advice method signature changes."],"tags":["spring-aop","aspectj","argument-binding","configuration","signature-mismatch"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}