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 the advice method's first parameter is ProceedingJoinPoint but supportsProceedingJoinPoint() returns false. The base implementation returns false; only AspectJAroundAdvice overrides it to return true. ProceedingJoinPoint.proceed() is only meaningful for around advice, so all other advice kinds reject it.

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 e8729d0438)

Solutions

  1. Change the advice annotation/element to @Around (or <aop:around>) if you need to call proceed().
  2. Replace ProceedingJoinPoint with JoinPoint in before/after/after-returning/after-throwing advice, which cannot proceed.
  3. Remove the join point parameter entirely if unused.

Example fix

// before
@After("execution(* svc.*(..))")
public void after(ProceedingJoinPoint pjp) { ... }
// after
@After("execution(* svc.*(..))")
public void after(JoinPoint jp) { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure ProceedingJoinPoint is only used on around advice before registering it.
Class<?> firstParam = adviceMethod.getParameterTypes()[0];
if (ProceedingJoinPoint.class == firstParam && !(advice instanceof AspectJAroundAdvice)) {
    throw new IllegalArgumentException(
        "ProceedingJoinPoint parameter requires @Around / <aop:around> on " + adviceMethod);
}

Type guard

private static boolean usesProceedingJoinPointCorrectly(Method m, AbstractAspectJAdvice a) {
    Class<?>[] pts = m.getParameterTypes();
    boolean firstIsPjp = pts.length > 0 && pts[0] == ProceedingJoinPoint.class;
    return !firstIsPjp || (a instanceof AspectJAroundAdvice);
}

Prevention

When it happens

Trigger: Declaring a ProceedingJoinPoint parameter on a @Before, @After, @AfterReturning, or @AfterThrowing advice method (or the XML equivalent), where the backing AbstractAspectJAdvice subclass is not AspectJAroundAdvice.

Common situations: Copy-pasting an around advice signature into a before/after advice; refactoring @Around to @After without removing the ProceedingJoinPoint parameter; mistakenly thinking all advice kinds can call proceed().

Related errors


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