spring-projects/spring-framework · error · UnsupportedOperationException

Only afterReturning advice can be used to bind a return valu

Error message

Only afterReturning advice can be used to bind a return value

What it means

The base AbstractAspectJAdvice.setReturningName(String) (line 291-293) is intentionally a guard: it throws UnsupportedOperationException because only after-returning advice semantics can bind a return value. The concrete AspectJAfterReturningAdvice overrides this method; calling it on any other advice subtype (before, after, after-throwing, around) hits this guard.

Source

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

			// May need to add implicit join point arg name...
			for (int i = 0; i < this.aspectJAdviceMethod.getParameterCount(); i++) {
				Class<?> argType = this.aspectJAdviceMethod.getParameterTypes()[i];
				if (argType == JoinPoint.class ||
						argType == ProceedingJoinPoint.class ||
						argType == JoinPoint.StaticPart.class) {
					@Nullable String[] oldNames = this.argumentNames;
				this.argumentNames = new String[oldNames.length + 1];
				System.arraycopy(oldNames, 0, this.argumentNames, 0, i);
					this.argumentNames[i] = "THIS_JOIN_POINT";
					System.arraycopy(oldNames, i, this.argumentNames, i + 1, oldNames.length - i);
					break;
				}
			}
		}
	}

	public void setReturningName(String name) {
		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 +

View on GitHub (pinned to e8729d0438)

Solutions

  1. Move the 'returning' attribute onto an <aop:after-returning> element (or @AfterReturning advice) only.
  2. Remove the 'returning' attribute from the before/after/after-throwing/around element causing the error.
  3. If binding a return value is genuinely needed, switch that advice to after-returning semantics.
  4. When building advice programmatically, only call setReturningName on an AspectJAfterReturningAdvice instance.

Example fix

// before
<aop:aspect ref="audit">
  <aop:after-throwing method="onEx" pointcut="..." returning="ret"/>
</aop:aspect>
// after
<aop:aspect ref="audit">
  <aop:after-returning method="onRet" pointcut="..." returning="ret"/>
</aop:aspect>
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

private static boolean supportsReturning(AbstractAspectJAdvice a) {
    return a instanceof AspectJAfterReturningAdvice;
}

Try / catch

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

Prevention

When it happens

Trigger: Invoking setReturningName on an AspectJMethodBeforeAdvice, AspectJAfterAdvice, AspectJAfterThrowingAdvice, or AspectJAroundAdvice instance, or configuring a 'returning' attribute on an <aop:before>, <aop:after>, <aop:after-throwing>, or <aop:around> element.

Common situations: XML misconfiguration: putting returning="ret" on the wrong advice element; copy-pasting an after-returning block and changing the advice kind without removing 'returning'; programmatically building advice objects and generically calling setReturningName.

Related errors


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