{"record":{"id":"ebd472a50125d95a","repo":"spring-projects/spring-framework","slug":"methodinvocation-is-not-a-spring-proxymethodinvoca-ebd472","errorCode":null,"errorMessage":"MethodInvocation is not a Spring ProxyMethodInvocation: {}","messagePattern":"MethodInvocation is not a Spring ProxyMethodInvocation: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java","lineNumber":359,"sourceCode":"\tpublic boolean isRuntime() {\n\t\treturn obtainPointcutExpression().mayNeedDynamicTest();\n\t}\n\n\t@Override\n\tpublic boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {\n\t\tShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);\n\n\t\t// Bind Spring AOP proxy to AspectJ \"this\" and Spring AOP target to AspectJ target,\n\t\t// consistent with return of MethodInvocationProceedingJoinPoint\n\t\tProxyMethodInvocation pmi = null;\n\t\tObject targetObject = null;\n\t\tObject thisObject = null;\n\t\ttry {\n\t\t\tMethodInvocation curr = ExposeInvocationInterceptor.currentInvocation();\n\t\t\tif (curr.getMethod() == method) {\n\t\t\t\ttargetObject = curr.getThis();\n\t\t\t\tif (!(curr instanceof ProxyMethodInvocation currPmi)) {\n\t\t\t\t\tthrow new IllegalStateException(\"MethodInvocation is not a Spring ProxyMethodInvocation: \" + curr);\n\t\t\t\t}\n\t\t\t\tpmi = currPmi;\n\t\t\t\tthisObject = pmi.getProxy();\n\t\t\t}\n\t\t}\n\t\tcatch (IllegalStateException ex) {\n\t\t\t// No current invocation...\n\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\tlogger.debug(\"Could not access current invocation - matching with limited context: \" + ex);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tJoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);\n\n\t\t\t/*\n\t\t\t * Do a final check to see if any this(TYPE) kind of residue match. For\n\t\t\t * this purpose, we use the original method's (proxy method's) shadow to","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java#L341-L377","documentation":"Thrown in AspectJExpressionPointcut.matches(method, targetClass, args) when the current thread-bound MethodInvocation (from ExposeInvocationInterceptor.currentInvocation()) is not a Spring ProxyMethodInvocation. This runtime-args matching path needs the proxy to correctly resolve this() bindings.","triggerScenarios":"An interceptor chain that uses ExposeInvocationInterceptor but pushes a non-Spring MethodInvocation into the thread local, or a non-Spring AOP Alliance interceptor running in the same thread as Spring advice matching.","commonSituations":"Mixing Spring AOP with other AOP Alliance frameworks, or custom MethodInvocation implementations that participate in Spring's ExposeInvocationInterceptor mechanism.","solutions":["Ensure the interceptor chain uses Spring's ReflectiveMethodInvocation / CglibMethodInvocation","Avoid mixing non-Spring MethodInvocation implementations in Spring-advised proxies","Register ExposeInvocationInterceptor only within Spring's own proxy infrastructure"],"exampleFix":"// before — custom MethodInvocation pushed into ExposeInvocationInterceptor\nExposeInvocationInterceptor.currentInvocation() returns non-Spring MI\n\n// after — use Spring ProxyMethodInvocation in the chain\nReflectiveMethodInvocation springMi = ...;\n// springMi implements ProxyMethodInvocation","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Type guard: check the current invocation is a ProxyMethodInvocation before relying on proxy state\nimport org.aopalliance.intercept.MethodInvocation;\nimport org.springframework.aop.ProxyMethodInvocation;\nimport org.springframework.aop.interceptor.ExposeInvocationInterceptor;\n\nMethodInvocation curr = ExposeInvocationInterceptor.currentInvocation();\nif (curr instanceof ProxyMethodInvocation pmi) {\n    Object proxy = pmi.getProxy(); // safe\n} else {\n    // Cannot resolve this() binding — skip or handle gracefully\n}","tryCatchPattern":null,"preventionTips":["Only use ExposeInvocationInterceptor within Spring's own proxy infrastructure","Do not push non-Spring MethodInvocation objects into the shared invocation thread local"],"tags":["spring-aop","aspectj","pointcut","proxy"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}