{"record":{"id":"1ea0391185cb5402","repo":"spring-projects/spring-framework","slug":"illegal-methodmatcher-usage","errorCode":null,"errorMessage":"Illegal MethodMatcher usage","messagePattern":"Illegal MethodMatcher usage","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/support/StaticMethodMatcher.java","lineNumber":41,"sourceCode":"import org.springframework.aop.MethodMatcher;\n\n/**\n * Convenient abstract superclass for static method matchers, which don't care\n * about arguments at runtime.\n *\n * @author Rod Johnson\n */\npublic abstract class StaticMethodMatcher implements MethodMatcher {\n\n\t@Override\n\tpublic final boolean isRuntime() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic final boolean matches(Method method, Class<?> targetClass, @Nullable Object... args) {\n\t\t// should never be invoked because isRuntime() returns false\n\t\tthrow new UnsupportedOperationException(\"Illegal MethodMatcher usage\");\n\t}\n\n}\n","sourceCodeStart":23,"sourceCodeEnd":45,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/support/StaticMethodMatcher.java#L23-L45","documentation":"Thrown by StaticMethodMatcher.matches(Method, Class, Object...) — the 3-argument runtime overload. StaticMethodMatcher.isRuntime() is final and returns false, meaning the matcher does not evaluate at runtime with argument values; the 3-arg matches is therefore final and throws UnsupportedOperationException because it should never be called by the framework.","triggerScenarios":"Directly invoking the 3-arg matches(method, targetClass, args) on an instance of a StaticMethodMatcher subclass; or a custom pointcut/advisor framework incorrectly dispatching the runtime variant without checking isRuntime().","commonSituations":"Third-party AOP code or a test calling the wrong matches overload; upgrading Spring versions where the method became final; writing a custom MethodMatcher delegate that forwards to a static matcher with the 3-arg signature.","solutions":["Call the 2-arg matches(Method, Class) on a StaticMethodMatcher — never the 3-arg runtime overload.","Before invoking the runtime overload, guard with matcher.isRuntime(); only call 3-arg matches when it returns true.","If you truly need runtime argument matching, subclass DynamicMethodMatcher instead of StaticMethodMatcher."],"exampleFix":"// before\nStaticMethodMatcher m = ...;\nm.matches(method, targetClass, args); // throws\n\n// after\nif (m.isRuntime()) { m.matches(method, targetClass, args); }\nelse { m.matches(method, targetClass); }","handlingStrategy":"type-guard","validationCode":"MethodMatcher m = ...;\nif (m.isRuntime()) {\n    m.matches(method, targetClass, args);\n} else {\n    m.matches(method, targetClass);\n}","typeGuard":"static boolean isRuntimeMatcher(MethodMatcher m) { return m.isRuntime(); }","tryCatchPattern":"try {\n    matcher.matches(method, targetClass, args);\n} catch (UnsupportedOperationException ex) {\n    // matcher is static; fall back to 2-arg matches\n    matcher.matches(method, targetClass);\n}","preventionTips":["Always gate the 3-arg matches on matcher.isRuntime().","Use StaticMethodMatcher only when you never need argument values; otherwise extend DynamicMethodMatcher.","In custom pointcut frameworks, branch on isRuntime() before dispatching."],"tags":["spring-aop","method-matcher","misuse","unsupported-operation"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}