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
- Change the advice annotation/element to @Around (or <aop:around>) if you need to call proceed().
- Replace ProceedingJoinPoint with JoinPoint in before/after/after-returning/after-throwing advice, which cannot proceed.
- 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
- Use ProceedingJoinPoint only in @Around advice; use JoinPoint elsewhere.
- When converting an @Around to another advice kind, swap ProceedingJoinPoint -> JoinPoint.
- Review advice signatures after any annotation/element-kind change.
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
- Only afterReturning advice can be used to bind a return valu
- Only afterThrowing advice can be used to bind a thrown excep
- An advice method can never be a constructor
- MethodInvocation is not a Spring ProxyMethodInvocation: {}
- Expecting {} arguments to proceed, but was passed {} argumen
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/8120aa076f558cd9.json.
Report an issue: GitHub.