{"record":{"id":"6f7f3b717a0002f9","repo":"spring-projects/spring-framework","slug":"returning-name-is-neither-a-valid-argument-na","errorCode":null,"errorMessage":"Returning name '{}' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. Root cause: {}","messagePattern":"Returning name '(.+?)' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath\\. Root cause: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":310,"sourceCode":"\t\tthrow new UnsupportedOperationException(\"Only afterReturning advice can be used to bind a return value\");\n\t}\n\n\t/**\n\t * We need to hold the returning name at this level for argument binding calculations,\n\t * this method allows the afterReturning advice subclass to set the name.\n\t */\n\tprotected void setReturningNameNoCheck(String name) {\n\t\t// name could be a variable or a type...\n\t\tif (isVariableName(name)) {\n\t\t\tthis.returningName = name;\n\t\t}\n\t\telse {\n\t\t\t// assume a type\n\t\t\ttry {\n\t\t\t\tthis.discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());\n\t\t\t}\n\t\t\tcatch (Throwable ex) {\n\t\t\t\tthrow new IllegalArgumentException(\"Returning name '\" + name +\n\t\t\t\t\t\t\"' is neither a valid argument name nor the fully-qualified \" +\n\t\t\t\t\t\t\"name of a Java type on the classpath. Root cause: \" + ex);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected Class<?> getDiscoveredReturningType() {\n\t\treturn this.discoveredReturningType;\n\t}\n\n\tprotected @Nullable Type getDiscoveredReturningGenericType() {\n\t\treturn this.discoveredReturningGenericType;\n\t}\n\n\tpublic void setThrowingName(String name) {\n\t\tthrow new UnsupportedOperationException(\"Only afterThrowing advice can be used to bind a thrown exception\");\n\t}\n","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L292-L328","documentation":"Thrown by setReturningNameNoCheck (line 299-314) when the returning value is neither a Java variable name (fails isVariableName) nor resolvable as a fully-qualified type via ClassUtils.forName using the aspect class loader. In the type form, Spring restricts the matched return type; in the variable form, it binds the actual return value. If neither interpretation works, binding is impossible.","triggerScenarios":"Setting returning=\"com.example.UnknownType\" where the type is not on the aspect's classpath, or returning=\"123bad\" / returning=\"return-value\" (not an identifier and not a type). Occurs via XML 'returning' attribute or @AfterReturning(returning=...) when the supplied value is misspelled.","commonSituations":"Misspelled fully-qualified class name in the returning attribute, a return type that lives in a module/jar not visible to the aspect class loader, or using a hyphenated/illegal identifier as the returning name. Common after refactoring that renames the bound type without updating the aspect XML/annotation.","solutions":["If you meant a variable name, use a valid Java identifier matching an advice parameter (e.g. returning=\"retVal\").","If you meant a type restriction, use the exact fully-qualified name and verify the class is on the aspect class loader (getAspectClassLoader()).","Check the root cause in the message — it typically contains a ClassNotFoundException naming the misspelled/missing type.","Ensure the jar containing the type is on the runtime classpath and not shaded out."],"exampleFix":"// before — misspelled package\n@AfterReturning(pointcut=\"execution(* svc.*(..))\", returning=\"com.exmaple.Result\")\npublic void after(Object r) {}\n\n// after — valid variable name binding to the advice parameter\n@AfterReturning(pointcut=\"execution(* svc.*(..))\", returning=\"r\")\npublic void after(Object r) {}","handlingStrategy":"validation","validationCode":"import org.springframework.util.ClassUtils;\n\n// Validate that 'returning' is either an identifier or a resolvable type before setting.\nvoid safeSetReturningName(AbstractAspectJAdvice advice, String name) {\n    if (isJavaIdentifier(name) || isLoadableType(name, advice.getAspectClassLoader())) {\n        advice.setReturningName(name); // routed to the afterReturning subclass\n    } else {\n        throw new IllegalArgumentException(\"returning '\" + name + \"' is neither identifier nor loadable type\");\n    }\n}\nboolean isLoadableType(String name, ClassLoader cl) {\n    try { ClassUtils.forName(name, cl); return true; } catch (Throwable t) { return false; }\n}","typeGuard":"boolean isReturningNameValid(String name, ClassLoader cl) {\n    if (name == null) return false;\n    if (Character.isJavaIdentifierStart(name.charAt(0))) {\n        return name.chars().skip(1).allMatch(Character::isJavaIdentifierPart);\n    }\n    try { Class.forName(name, false, cl); return true; } catch (Throwable t) { return false; }\n}","tryCatchPattern":"try {\n    ((AspectJAfterReturningAdvice) advice).setReturningName(name);\n} catch (IllegalArgumentException ex) {\n    // check root cause for ClassNotFoundException; fix the type/identifier\n}","preventionTips":["Use a variable name matching an advice parameter rather than a type unless restricting the return type.","Confirm the type jar is on the aspect class loader.","Re-validate the returning attribute after refactoring return types."],"tags":["spring-aop","aspectj","after-returning","classpath","argument-binding"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}