spring-projects/spring-framework · error · IllegalStateException
MethodInvocation is not a Spring ProxyMethodInvocation
Error message
MethodInvocation is not a Spring ProxyMethodInvocation: {} What it means
Thrown by the static currentJoinPoint() helper when the AOP Alliance MethodInvocation exposed via ExposeInvocationInterceptor is not an instance of Spring's ProxyMethodInvocation. Spring's advice machinery caches the JoinPoint as a user attribute on a ProxyMethodInvocation; if some other Advice or framework drives the invocation with a plain MethodInvocation, that lookup mechanism is unavailable. The guard at line 82-84 therefore refuses to proceed rather than return a half-built join point.
Solutions
- Ensure the invocation is driven through a Spring ProxyFactory / AspectJProxyFactory so the active MethodInvocation is a ReflectiveMethodInvocation (which implements ProxyMethodInvocation).
- Add ExposeInvocationInterceptor to the advice chain if it is missing — it is what publishes the current ProxyMethodInvocation via ExposeInvocationInterceptor.currentInvocation().
- If calling from outside Spring AOP, wrap your target in an AspectJProxyFactory and obtain the proxy from it rather than invoking advice reflectively.
- In tests, build the invocation with ReflectiveMethodInvocation.createInvocation(target, method, args, targetClass, interceptorsAndAdvice) so the instance is a ProxyMethodInvocation.
Example fix
// before: invoking advice with a plain mock MethodInvocation advice.invoke(new MyCustomMethodInvocation()); // after: drive through a Spring proxy so currentInvocation() is a ProxyMethodInvocation AspectJProxyFactory factory = new AspectJProxyFactory(target); factory.addAspect(myAspect); MyInterface proxy = factory.getProxy(); proxy.businessMethod();
Defensive patterns
Strategy: type-guard
Validate before calling
import org.springframework.aop.ProxyMethodInvocation;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
// Verify a Spring ProxyMethodInvocation is active before calling currentJoinPoint().
boolean safeToCallJoinPoint() {
try {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
return mi instanceof ProxyMethodInvocation;
} catch (IllegalStateException noInvocation) {
return false;
}
} Type guard
boolean isSpringProxyInvocation(org.aopalliance.intercept.MethodInvocation mi) {
return mi instanceof org.springframework.aop.ProxyMethodInvocation;
} Try / catch
try {
JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("not a Spring ProxyMethodInvocation")) {
// advice invoked outside a Spring proxy; re-route through AspectJProxyFactory
} else { throw ex; }
} Prevention
- Always obtain advice-bearing proxies from ProxyFactory/AspectJProxyFactory, never invoke advice reflectively with a custom MethodInvocation.
- Keep ExposeInvocationInterceptor in the chain when using AspectJ-style binding.
- In tests, build invocations with ReflectiveMethodInvocation so they are ProxyMethodInvocations.
When it happens
Trigger: Calling AbstractAspectJAdvice.currentJoinPoint() (or any advice that delegates to it, e.g. AspectJMethodBeforeAdvice) from within a non-Spring interceptor chain — for example a custom org.aopalliance.intercept.MethodInterceptor registered outside ProxyFactory, or invoking advice directly during a unit test without a ReflectiveMethodInvocation. Also when ExposeInvocationInterceptor is absent from the advice chain yet code still calls currentJoinPoint().
Common situations: Manually wiring Spring AspectJ advice into a non-Spring proxy (CGLIB directly, ByteBuddy, javassist), unit-testing advice by hand-rolling a MethodInvocation, or removing ExposeInvocationInterceptor from the advisor chain while still relying on AspectJ-style thisJoinPoint binding. Occasionally seen after upgrading a custom proxy bridge between Spring AOP and another framework.
Related errors
- MethodInvocation is not a Spring ProxyMethodInvocation
- MethodInvocation is not a Spring ProxyMethodInvocation
- Advice method [ ] requires arguments to be bound by name…
- Advice must be declared inside an aspect type: Offending…
- Advice object [ ] is neither a supported subinterface of…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/a8c750e4e22e6eac.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:83
/**
* Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
*/
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
/**
* Lazily instantiate joinpoint for the current invocation.
* Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
* <p>Do not use if access is available to the current ReflectiveMethodInvocation
* (in an around advice).
* @return current AspectJ joinpoint, or through an exception if we're not in a
* Spring AOP invocation.
*/
public static JoinPoint currentJoinPoint() {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation pmi)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
if (jp == null) {
jp = new MethodInvocationProceedingJoinPoint(pmi);
pmi.setUserAttribute(JOIN_POINT_KEY, jp);
}
return jp;
}
private final Class<?> declaringClass;
private final String methodName;
private final Class<?>[] parameterTypes;
protected transient Method aspectJAdviceMethod;
View on GitHub (pinned to 69bf83ad71)