spring-projects/spring-framework · error · IllegalArgumentException
Returning name ' ' is neither a valid argument name nor the…
Error message
Returning name '{}' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. Root cause: {} What it means
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.
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.
Example fix
// before — misspelled package
@AfterReturning(pointcut="execution(* svc.*(..))", returning="com.exmaple.Result")
public void after(Object r) {}
// after — valid variable name binding to the advice parameter
@AfterReturning(pointcut="execution(* svc.*(..))", returning="r")
public void after(Object r) {} Defensive patterns
Strategy: validation
Validate before calling
import org.springframework.util.ClassUtils;
// Validate that 'returning' is either an identifier or a resolvable type before setting.
void safeSetReturningName(AbstractAspectJAdvice advice, String name) {
if (isJavaIdentifier(name) || isLoadableType(name, advice.getAspectClassLoader())) {
advice.setReturningName(name); // routed to the afterReturning subclass
} else {
throw new IllegalArgumentException("returning '" + name + "' is neither identifier nor loadable type");
}
}
boolean isLoadableType(String name, ClassLoader cl) {
try { ClassUtils.forName(name, cl); return true; } catch (Throwable t) { return false; }
} Type guard
boolean isReturningNameValid(String name, ClassLoader cl) {
if (name == null) return false;
if (Character.isJavaIdentifierStart(name.charAt(0))) {
return name.chars().skip(1).allMatch(Character::isJavaIdentifierPart);
}
try { Class.forName(name, false, cl); return true; } catch (Throwable t) { return false; }
} Try / catch
try {
((AspectJAfterReturningAdvice) advice).setReturningName(name);
} catch (IllegalArgumentException ex) {
// check root cause for ClassNotFoundException; fix the type/identifier
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Returning argument name
- Throwing name ' ' is neither a valid argument name nor the…
- Advice method [ ] requires arguments to be bound by name…
- 'argumentNames' property of AbstractAspectJAdvice contains…
- Binding of returning parameter
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/6f7f3b717a0002f9.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:310
throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
}
/**
* We need to hold the returning name at this level for argument binding calculations,
* this method allows the afterReturning advice subclass to set the name.
*/
protected void setReturningNameNoCheck(String name) {
// name could be a variable or a type...
if (isVariableName(name)) {
this.returningName = name;
}
else {
// assume a type
try {
this.discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());
}
catch (Throwable ex) {
throw new IllegalArgumentException("Returning name '" + name +
"' is neither a valid argument name nor the fully-qualified " +
"name of a Java type on the classpath. Root cause: " + ex);
}
}
}
protected Class<?> getDiscoveredReturningType() {
return this.discoveredReturningType;
}
protected @Nullable Type getDiscoveredReturningGenericType() {
return this.discoveredReturningGenericType;
}
public void setThrowingName(String name) {
throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
}
View on GitHub (pinned to 69bf83ad71)