spring-projects/spring-framework · error · UnsupportedOperationException

Only afterThrowing advice can be used to bind a thrown excep

Error message

Only afterThrowing advice can be used to bind a thrown exception

What it means

The base AbstractAspectJAdvice.setThrowingName(String) (line 325-327) is a guard that throws UnsupportedOperationException: only after-throwing advice can bind a thrown exception. AspectJAfterThrowingAdvice overrides this method; any other advice subtype retains the throwing base implementation and rejects the call.

Source

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

			}
			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");
	}

	/**
	 * 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 +

View on GitHub (pinned to e8729d0438)

Solutions

  1. Place the 'throwing' attribute only on an <aop:after-throwing> element (or @AfterThrowing advice).
  2. Remove 'throwing' from the before/after/after-returning/around element causing the error.
  3. For around advice, capture exceptions via try/catch around pjp.proceed() instead of a throwing binding.
  4. When building advice programmatically, call setThrowingName only on AspectJAfterThrowingAdvice.

Example fix

// before
@Around(value = "execution(* svc.*(..))", throwing = "ex")
public Object around(ProceedingJoinPoint pjp, Exception ex) { ... }
// after
@AfterThrowing(value = "execution(* svc.*(..))", throwing = "ex")
public void onThrow(Exception ex) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Only call setThrowingName on the correct advice subtype.
if (advice instanceof AspectJAfterThrowingAdvice) {
    advice.setThrowingName(name);
} else {
    throw new IllegalStateException("throwing binding requires after-throwing advice, got " + advice.getClass());
}

Type guard

private static boolean supportsThrowing(AbstractAspectJAdvice a) {
    return a instanceof AspectJAfterThrowingAdvice;
}

Try / catch

try {
    advice.setThrowingName(name);
} catch (UnsupportedOperationException ex) {
    throw new IllegalStateException(
        "'throwing' is only valid on after-throwing advice; remove it from " + advice.getClass().getSimpleName(), ex);
}

Prevention

When it happens

Trigger: Calling setThrowingName (or configuring a 'throwing' attribute) on AspectJMethodBeforeAdvice, AspectJAfterAdvice, AspectJAfterReturningAdvice, or AspectJAroundAdvice, i.e. putting throwing="..." on <aop:before>, <aop:after>, <aop:after-returning>, or <aop:around>.

Common situations: XML/annotation misconfiguration: reusing an after-throwing block as a template and leaving 'throwing' on the now-different advice kind; expecting exception binding on around advice (around should catch via proceed() instead).

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/7ace6b6180ba2a12.json. Report an issue: GitHub.