{"id":"a6cc4a4354a15f26","repo":"spring-projects/spring-framework","slug":"binding-of-throwing-parameter-could-not-be-co","errorCode":null,"errorMessage":"Binding of throwing parameter '{}' could not be completed as no available arguments are a subtype of Throwable","messagePattern":"Binding of throwing parameter '(.+?)' could not be completed as no available arguments are a subtype of Throwable","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java","lineNumber":351,"sourceCode":"\n\t\t// So there is binding work to do...\n\t\tint throwableIndex = -1;\n\t\tfor (int i = 0; i < this.argumentTypes.length; i++) {\n\t\t\tif (isUnbound(i) && isSubtypeOf(Throwable.class, i)) {\n\t\t\t\tif (throwableIndex == -1) {\n\t\t\t\t\tthrowableIndex = i;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Second candidate we've found - ambiguous binding\n\t\t\t\t\tthrow new AmbiguousBindingException(\"Binding of throwing parameter '\" +\n\t\t\t\t\t\t\tthis.throwingName + \"' is ambiguous: could be bound to argument \" +\n\t\t\t\t\t\t\tthrowableIndex + \" or \" + i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (throwableIndex == -1) {\n\t\t\tthrow new IllegalStateException(\"Binding of throwing parameter '\" + this.throwingName +\n\t\t\t\t\t\"' could not be completed as no available arguments are a subtype of Throwable\");\n\t\t}\n\t\telse {\n\t\t\tbindParameterName(throwableIndex, this.throwingName);\n\t\t}\n\t}\n\n\t/**\n\t * If a returning variable was specified and there is only one choice remaining, bind it.\n\t */\n\tprivate void maybeBindReturningVariable() {\n\t\tif (this.numberOfRemainingUnboundArguments == 0) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"Algorithm assumes that there must be at least one unbound parameter on entry to this method\");\n\t\t}\n\n\t\tif (this.returningName != null) {\n\t\t\tif (this.numberOfRemainingUnboundArguments > 1) {","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java#L333-L369","documentation":"Thrown by maybeBindThrowingVariable (line 350-353) when throwingName is set but no unbound advice parameter is a subtype of Throwable. The throwing binding requires a Throwable-typed parameter to receive the exception; if none exists, binding is impossible.","triggerScenarios":"Configuring after-throwing with throwing='ex' but the advice method has no parameter whose type is a Throwable (e.g. all params are business types or a JoinPoint), and parameter names are unavailable so type-based matching is attempted.","commonSituations":"Forgetting to add the exception parameter to the advice method; declaring the throwing attribute but the method only has a JoinPoint/business params; renaming/removing the exception parameter without dropping the throwing attribute.","solutions":["Add a Throwable (or specific exception subtype) parameter to the advice method that matches the throwing name.","Compile with -parameters and ensure a parameter is named exactly as the throwing attribute, with a Throwable type.","Remove the throwing attribute if you do not need to bind the exception."],"exampleFix":"// before\n@AfterThrowing(value = \"...\", throwing = \"ex\")\npublic void onThrow(JoinPoint jp) { ... } // no Throwable param\n// after\n@AfterThrowing(value = \"...\", throwing = \"ex\")\npublic void onThrow(JoinPoint jp, Throwable ex) { ... }","handlingStrategy":"validation","validationCode":"// Before wiring after-throwing, ensure a Throwable param exists when throwing is set.\nboolean hasThrowableParam = Arrays.stream(adviceMethod.getParameterTypes())\n    .anyMatch(Throwable.class::isAssignableFrom);\nif (throwingName != null && !hasThrowableParam) {\n    throw new IllegalStateException(\"throwing='\" + throwingName\n        + \"' set but \" + adviceMethod + \" has no Throwable parameter\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare a Throwable (or specific subtype) parameter when using the throwing attribute.","Compile with -parameters and name the parameter to match the throwing attribute exactly.","Remove the throwing attribute if you do not bind the exception."],"tags":["spring-aop","aspectj","after-throwing","argument-binding","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}