{"record":{"id":"debd956669cfdd0f","repo":"spring-projects/spring-framework","slug":"cannot-invoke-methods","errorCode":null,"errorMessage":"Cannot invoke methods: {}","messagePattern":"Cannot invoke methods: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java","lineNumber":613,"sourceCode":"\t */\n\tprivate static class PrototypePlaceholderAdvisor implements Advisor, Serializable {\n\n\t\tprivate final String beanName;\n\n\t\tprivate final String message;\n\n\t\tpublic PrototypePlaceholderAdvisor(String beanName) {\n\t\t\tthis.beanName = beanName;\n\t\t\tthis.message = \"Placeholder for prototype Advisor/Advice with bean name '\" + beanName + \"'\";\n\t\t}\n\n\t\tpublic String getBeanName() {\n\t\t\treturn this.beanName;\n\t\t}\n\n\t\t@Override\n\t\tpublic Advice getAdvice() {\n\t\t\tthrow new UnsupportedOperationException(\"Cannot invoke methods: \" + this.message);\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn this.message;\n\t\t}\n\t}\n\n}\n","sourceCodeStart":595,"sourceCodeEnd":623,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java#L595-L623","documentation":"Thrown as UnsupportedOperationException by ProxyFactoryBean's private PrototypePlaceholderAdvisor.getAdvice(). Placeholders stand in for prototype-scoped advice beans during chain construction and are normally resolved (replaced with a real Advisor) before being used. Calling getAdvice() directly on the placeholder is illegal; it only exists to hold the bean name until refresh.","triggerScenarios":"Introspecting getAdvisors() on a ProxyFactoryBean that has prototype advisors in its chain and immediately calling getAdvice() on the returned Advisor before the prototype is materialized — for example, custom code walking the advisor chain of a freshly-built prototype proxy before resolution, or a debug/inspection tool.","commonSituations":"Diagnostic code that iterates getAdvisors() and calls .getAdvice() to log details; test code asserting on advisor types before the prototype lookup has run; integration with libraries that walk the advised chain.","solutions":["Do not call getAdvice() on advisors returned by a prototype ProxyFactoryBean before the chain is materialized; trigger resolution first by getting a fresh prototype instance.","Switch the prototype-scoped advice to a singleton so no placeholder is used.","Use instanceof checks against known advice types and skip placeholders (their toString() carries the bean name)."],"exampleFix":"// before\nfor (Advisor a : factoryBean.getAdvisors()) {\n  Advice ad = a.getAdvice(); // throws on placeholder\n}\n\n// after\nfor (Advisor a : factoryBean.getAdvisors()) {\n  if (a.getClass().getSimpleName().contains(\"Placeholder\")) continue;\n  Advice ad = a.getAdvice();\n}","handlingStrategy":"type-guard","validationCode":"for (Advisor a : pfb.getAdvisors()) {\n  if (a.getClass().getName().contains(\"PrototypePlaceholderAdvisor\")) continue;\n  Advice ad = a.getAdvice();\n}","typeGuard":"static boolean isPlaceholder(Advisor a) {\n  return a.getClass().getName().contains(\"PrototypePlaceholderAdvisor\");\n}","tryCatchPattern":"try { advice = a.getAdvice(); }\ncatch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Cannot invoke methods\")) { /* skip placeholder */ }\n  throw e;\n}","preventionTips":["Do not introspect getAdvice() on advisors of a prototype ProxyFactoryBean before resolution.","Prefer singleton advice to avoid placeholders entirely.","Filter by advisor class name when walking the chain for diagnostics."],"tags":["spring-aop","proxyfactorybean","prototype","advisor","introspection"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}