spring-projects/spring-framework · error · IllegalArgumentException

ProceedingJoinPoint is only supported for around advice

Error message

ProceedingJoinPoint is only supported for around advice

What it means

Thrown by maybeBindProceedingJoinPoint (line 405-416) when an advice method declares a parameter of type ProceedingJoinPoint but supportsProceedingJoinPoint() returns false. The base class returns false (line 418-420); only AspectJAroundAdvice overrides it to true. ProceedingJoinPoint.proceed() requires the ability to resume the target invocation, which only around advice can offer.

Solutions

  1. Change the advice annotation/element to @Around / <aop:around> so supportsProceedingJoinPoint() is true.
  2. Or change the parameter type from ProceedingJoinPoint to JoinPoint (for before/after/afterReturning/afterThrowing).
  3. If you need to proceed, you must use around advice — there is no workaround.

Example fix

// before — ProceedingJoinPoint on a non-around advice
@Before("execution(* svc.*(..))")
public void check(ProceedingJoinPoint pjp) { /* cannot proceed */ }

// after — either use @Around with proceed(), or @Before with JoinPoint
@Around("execution(* svc.*(..))")
public Object check(ProceedingJoinPoint pjp) throws Throwable { return pjp.proceed(); }
Defensive patterns

Strategy: type-guard

Validate before calling

import org.aspectj.lang.ProceedingJoinPoint;
import java.lang.reflect.Method;

// Reject non-around advice that declares a ProceedingJoinPoint parameter.
void assertNoProceedingJoinPointUnlessAround(Method adviceMethod, boolean isAround) {
    if (!isAround && adviceMethod.getParameterCount() > 0
            && adviceMethod.getParameterTypes()[0] == ProceedingJoinPoint.class) {
        throw new IllegalArgumentException(
            "ProceedingJoinPoint requires around advice: " + adviceMethod);
    }
}

Type guard

boolean usesProceedingJoinPoint(Method m) {
    return m.getParameterCount() > 0
        && m.getParameterTypes()[0] == org.aspectj.lang.ProceedingJoinPoint.class;
}

Try / catch

try {
    advice.calculateArgumentBindings();
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().contains("ProceedingJoinPoint")) {
        // switch the advice to @Around, or change the param to JoinPoint
    } else { throw ex; }
}

Prevention

When it happens

Trigger: Declaring a ProceedingJoinPoint parameter on a @Before, @After, @AfterReturning, or @AfterThrowing method, or an <aop:before>/<aop:after> element whose method takes org.aspectj.lang.ProceedingJoinPoint. Also when programmatically constructing AspectJMethodBeforeAdvice for a method that uses ProceedingJoinPoint.

Common situations: Changing an @Around advice to @Before/@After and forgetting to change the parameter type from ProceedingJoinPoint to JoinPoint. Copy-pasting an around-advice signature into a non-around advice. XML where method='before' but the method signature expects a ProceedingJoinPoint.

Related errors


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

Appendix: source

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

		}

		this.argumentsIntrospected = true;
	}

	private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
		if (JoinPoint.class == candidateParameterType) {
			this.joinPointArgumentIndex = 0;
			return true;
		}
		else {
			return false;
		}
	}

	private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
		if (ProceedingJoinPoint.class == candidateParameterType) {
			if (!supportsProceedingJoinPoint()) {
				throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
			}
			this.joinPointArgumentIndex = 0;
			return true;
		}
		else {
			return false;
		}
	}

	protected boolean supportsProceedingJoinPoint() {
		return false;
	}

	private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
		if (JoinPoint.StaticPart.class == candidateParameterType) {
			this.joinPointStaticPartArgumentIndex = 0;
			return true;
		}

View on GitHub (pinned to 69bf83ad71)