spring-projects/spring-framework · error · IllegalArgumentException

Throwing name ' ' is neither a valid argument name nor the…

Error message

Throwing 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 setThrowingNameNoCheck (line 333-348) when the throwing value is neither a Java variable name (fails isVariableName) nor resolvable as a fully-qualified type via ClassUtils.forName on the aspect class loader. In type form it restricts which exception types trigger the advice; in variable form it binds the thrown exception. Failure of both means binding cannot proceed.

Solutions

  1. If you meant a variable name, use a valid Java identifier matching an advice parameter of a Throwable subtype (e.g. throwing="ex").
  2. If you meant a type restriction, use the exact fully-qualified exception name and confirm it is visible to getAspectClassLoader().
  3. Read the root cause (usually ClassNotFoundException) in the message to locate the missing type.
  4. Rebuild/redeploy so the exception class is on the runtime classpath.

Example fix

// before — misspelled exception type
@AfterThrowing(pointcut="execution(* svc.*(..))", throwing="java.lang.RuntimeErr")
public void onError(Throwable t) {}

// after — valid variable name bound to the advice parameter
@AfterThrowing(pointcut="execution(* svc.*(..))", throwing="t")
public void onError(Throwable t) {}
Defensive patterns

Strategy: validation

Validate before calling

import org.springframework.util.ClassUtils;

void safeSetThrowingName(AbstractAspectJAdvice advice, String name) {
    if (isJavaIdentifier(name) || isLoadableType(name, advice.getAspectClassLoader())) {
        advice.setThrowingName(name); // routed to the afterThrowing subclass
    } else {
        throw new IllegalArgumentException("throwing '" + 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 isThrowingNameValid(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 {
    ((AspectJAfterThrowingAdvice) advice).setThrowingName(name);
} catch (IllegalArgumentException ex) {
    // root cause is usually ClassNotFoundException; correct the name/classpath
}

Prevention

When it happens

Trigger: Setting throwing="java.io.NonexistentException" where the type is not on the classpath, or throwing="err-code" (neither identifier nor type). Occurs via XML 'throwing' attribute or @AfterThrowing(throwing=...) when the value is wrong.

Common situations: Misspelled exception class name, a custom exception class in a jar not loaded by the aspect class loader, or using a non-identifier string as the throwing name. Common after moving exception classes between packages.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/f59a4db5f7231f69. Report an issue: GitHub.

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:344

		throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
	}

	/**
	 * We need to hold the throwing name at this level for argument binding calculations,
	 * this method allows the afterThrowing advice subclass to set the name.
	 */
	protected void setThrowingNameNoCheck(String name) {
		// name could be a variable or a type...
		if (isVariableName(name)) {
			this.throwingName = name;
		}
		else {
			// assume a type
			try {
				this.discoveredThrowingType = ClassUtils.forName(name, getAspectClassLoader());
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException("Throwing 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<?> getDiscoveredThrowingType() {
		return this.discoveredThrowingType;
	}

	@Contract("null -> false")
	private static boolean isVariableName(@Nullable String name) {
		return AspectJProxyUtils.isVariableName(name);
	}


	/**
	 * Do as much work as we can as part of the set-up so that argument binding

View on GitHub (pinned to 69bf83ad71)