{"id":"f54af64e1cdca7b9","repo":"spring-projects/spring-framework","slug":"unsupported-afterthrowing-signature-single-throwa","errorCode":null,"errorMessage":"Unsupported afterThrowing signature: single throwable argument or four arguments Method, Object[], target, throwable expected: {method}","messagePattern":"Unsupported afterThrowing signature: single throwable argument or four arguments Method, Object\\[\\], target, throwable expected: (.+?)","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java","lineNumber":103,"sourceCode":"\t\t\t\t\t// just a Throwable parameter\n\t\t\t\t\tthrowableParam = method.getParameterTypes()[0];\n\t\t\t\t\tif (!Throwable.class.isAssignableFrom(throwableParam)) {\n\t\t\t\t\t\tthrow new AopConfigException(\"Invalid afterThrowing signature: \" +\n\t\t\t\t\t\t\t\t\"single argument must be a Throwable subclass\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (method.getParameterCount() == 4) {\n\t\t\t\t\t// Method, Object[], target, throwable\n\t\t\t\t\tClass<?>[] paramTypes = method.getParameterTypes();\n\t\t\t\t\tif (!Method.class.equals(paramTypes[0]) || !Object[].class.equals(paramTypes[1]) ||\n\t\t\t\t\t\t\tThrowable.class.equals(paramTypes[2]) || !Throwable.class.isAssignableFrom(paramTypes[3])) {\n\t\t\t\t\t\tthrow new AopConfigException(\"Invalid afterThrowing signature: \" +\n\t\t\t\t\t\t\t\t\"four arguments must be Method, Object[], target, throwable: \" + method);\n\t\t\t\t\t}\n\t\t\t\t\tthrowableParam = paramTypes[3];\n\t\t\t\t}\n\t\t\t\tif (throwableParam == null) {\n\t\t\t\t\tthrow new AopConfigException(\"Unsupported afterThrowing signature: single throwable argument \" +\n\t\t\t\t\t\t\t\"or four arguments Method, Object[], target, throwable expected: \" + method);\n\t\t\t\t}\n\t\t\t\t// An exception handler to register...\n\t\t\t\tMethod existingMethod = this.exceptionHandlerMap.put(throwableParam, method);\n\t\t\t\tif (existingMethod != null) {\n\t\t\t\t\tthrow new AopConfigException(\"Only one afterThrowing method per specific Throwable subclass \" +\n\t\t\t\t\t\t\t\"allowed: \" + method + \" / \" + existingMethod);\n\t\t\t\t}\n\t\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\t\tlogger.debug(\"Found exception handler method on throws advice: \" + method);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.exceptionHandlerMap.isEmpty()) {\n\t\t\tthrow new AopConfigException(\n\t\t\t\t\t\"At least one handler method must be found in class [\" + throwsAdvice.getClass() + \"]\");\n\t\t}","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/framework/adapter/ThrowsAdviceInterceptor.java#L85-L121","documentation":"If an afterThrowing method has neither 1 nor 4 parameters, throwableParam stays null and AopConfigException is thrown. Only the single-throwable and the full 4-arg forms are recognized - zero, two, three, or five+ arg variants are unsupported.","triggerScenarios":"Defining afterThrowing() with 0 args, 2 args, 3 args, or 5+ args; an accidental helper method also named afterThrowing with a different arity.","commonSituations":"Refactoring that changes parameter lists; leftover debug/overloaded methods named afterThrowing; misunderstanding that only 1- and 4-arg forms are allowed.","solutions":["Reduce to either afterThrowing(ThrowableSubclass) or afterThrowing(Method, Object[], Object, ThrowableSubclass).","Rename any unrelated helper methods that happen to be called 'afterThrowing'.","Review all public methods named afterThrowing on the advice class."],"exampleFix":"// before\npublic void afterThrowing(Method m, Object target, Exception ex) {} // 3 args\n\n// after\npublic void afterThrowing(Method m, Object[] args, Object target, Exception ex) {} // 4 args","handlingStrategy":"validation","validationCode":"for (Method m : advice.getClass().getMethods()) {\n    if (m.getName().equals(\"afterThrowing\") && m.getParameterCount() != 1 && m.getParameterCount() != 4) {\n        throw new IllegalStateException(\"afterThrowing must have 1 or 4 args: \" + m);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare afterThrowing with either 1 or 4 parameters only.","Rename any unrelated helper methods that share the name 'afterThrowing'.","Audit the advice class for stray overloads during code review."],"tags":["aop","throws-advice","signature","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}