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
- Change the advice annotation/element to @Around / <aop:around> so supportsProceedingJoinPoint() is true.
- Or change the parameter type from ProceedingJoinPoint to JoinPoint (for before/after/afterReturning/afterThrowing).
- 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
- Use ProceedingJoinPoint only in @Around advice; use JoinPoint elsewhere.
- When converting @Around to another advice type, also change the parameter type.
- Add a CI check that scans advice methods for ProceedingJoinPoint misuse.
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
- Expecting arguments to proceed, but was passed arguments
- MethodInvocation is not a Spring ProxyMethodInvocation
- Only afterReturning advice can be used to bind a return…
- Only afterThrowing advice can be used to bind a thrown…
- Advice method [ ] requires arguments to be bound by name…
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)