spring-projects/spring-framework · error · IllegalArgumentException
MethodInvocation is not a Spring ProxyMethodInvocation
Error message
MethodInvocation is not a Spring ProxyMethodInvocation: {mi} What it means
Thrown by ExposeBeanNameAdvisors.getBeanName(MethodInvocation) (line 71-73) when the passed MethodInvocation is not an instance of Spring's ProxyMethodInvocation. The bean name is stored as a user attribute on the ProxyMethodInvocation; a generic AOP Alliance MethodInvocation has no user-attribute API, so the lookup cannot proceed and an IllegalArgumentException is raised.
Solutions
- Ensure the MethodInvocation you pass is a Spring ProxyMethodInvocation (e.g. ReflectiveMethodInvocation, or the one Spring supplies during proxy invocation).
- In tests, pass a mock of ProxyMethodInvocation and stub getUserAttribute/setUserAttribute.
- Only invoke getBeanName(mi) from within a Spring-managed proxy chain, not from arbitrary invocation objects.
Example fix
// before
MethodInvocation mi = mock(MethodInvocation.class);
String name = ExposeBeanNameAdvisors.getBeanName(mi); // fails
// after
ProxyMethodInvocation mi = mock(ProxyMethodInvocation.class);
when(mi.getUserAttribute(anyString())).thenReturn("myBean");
String name = ExposeBeanNameAdvisors.getBeanName(mi); Defensive patterns
Strategy: type-guard
Validate before calling
import org.springframework.aop.ProxyMethodInvocation;
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalArgumentException("Need a Spring ProxyMethodInvocation");
} Type guard
static boolean isSpringProxyInvocation(MethodInvocation mi) {
return mi instanceof ProxyMethodInvocation;
} Prevention
- Call ExposeBeanNameAdvisors.getBeanName only on Spring ProxyMethodInvocations.
- In tests, mock ProxyMethodInvocation, not the bare interface.
- Run bean-name lookups inside Spring-managed proxy chains.
When it happens
Trigger: Calling ExposeBeanNameAdvisors.getBeanName(mi) where 'mi' is a hand-rolled or third-party MethodInvocation implementation that does not implement org.springframework.aop.ProxyMethodInvocation. This includes unit tests passing a mocked MethodInvocation that is not typed as ProxyMethodInvocation.
Common situations: Unit-testing advice that reads the bean name by passing a plain mock MethodInvocation. Using a non-Spring AOP framework's invocation inside a Spring-advised chain. Calling getBeanName from a thread that received a raw MethodInvocation.
Related errors
- Need to invoke method
- is not a valid AspectJ annotation
- AOP configuration seems to be invalid: tried calling method
- At least one handler method must be found in class
- Cannot create class proxy for TargetSource with null target…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/c47b7e918997ec72.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/interceptor/ExposeBeanNameAdvisors.java:72
* has been included in the interceptor chain, and that the invocation is exposed
* with ExposeInvocationInterceptor.
* @return the bean name (never {@code null})
* @throws IllegalStateException if the bean name has not been exposed
*/
public static String getBeanName() throws IllegalStateException {
return getBeanName(ExposeInvocationInterceptor.currentInvocation());
}
/**
* Find the bean name for the given invocation. Assumes that an ExposeBeanNameAdvisor
* has been included in the interceptor chain.
* @param mi the MethodInvocation that should contain the bean name as an attribute
* @return the bean name (never {@code null})
* @throws IllegalStateException if the bean name has not been exposed
*/
public static String getBeanName(MethodInvocation mi) throws IllegalStateException {
if (!(mi instanceof ProxyMethodInvocation pmi)) {
throw new IllegalArgumentException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
String beanName = (String) pmi.getUserAttribute(BEAN_NAME_ATTRIBUTE);
if (beanName == null) {
throw new IllegalStateException("Cannot get bean name; not set on MethodInvocation: " + mi);
}
return beanName;
}
/**
* Create a new advisor that will expose the given bean name,
* with no introduction.
* @param beanName bean name to expose
*/
public static Advisor createAdvisorWithoutIntroduction(String beanName) {
return new DefaultPointcutAdvisor(new ExposeBeanNameInterceptor(beanName));
}
/**View on GitHub (pinned to 69bf83ad71)