{"id":"bff89e43a6d16c60","repo":"spring-projects/spring-framework","slug":"failed-to-find-advice-method-on-deserialization","errorCode":null,"errorMessage":"Failed to find advice method on deserialization","messagePattern":"Failed to find advice method on deserialization","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":702,"sourceCode":"\tprotected @Nullable JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {\n\t\tString expression = this.pointcut.getExpression();\n\t\treturn (expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null);\n\t}\n\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getClass().getName() + \": advice method [\" + this.aspectJAdviceMethod + \"]; \" +\n\t\t\t\t\"aspect name '\" + this.aspectName + \"'\";\n\t}\n\n\tprivate void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {\n\t\tinputStream.defaultReadObject();\n\t\ttry {\n\t\t\tthis.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);\n\t\t}\n\t\tcatch (NoSuchMethodException ex) {\n\t\t\tthrow new IllegalStateException(\"Failed to find advice method on deserialization\", ex);\n\t\t}\n\t}\n\n\n\t/**\n\t * MethodMatcher that excludes the specified advice method.\n\t * @see AbstractAspectJAdvice#buildSafePointcut()\n\t */\n\tprivate static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {\n\n\t\tprivate final Method adviceMethod;\n\n\t\tpublic AdviceExcludingMethodMatcher(Method adviceMethod) {\n\t\t\tthis.adviceMethod = adviceMethod;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean matches(Method method, Class<?> targetClass) {","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L684-L720","documentation":"Thrown by readObject (line 696-704) during Java deserialization of an AbstractAspectJAdvice: defaultReadObject restores the declaring class, method name, and parameter types, then declaringClass.getMethod(name, types) is attempted. If the method no longer exists (renamed, signature changed, removed, moved class), NoSuchMethodException is wrapped in this IllegalStateException.","triggerScenarios":"Deserializing a previously serialized advice (e.g. from a cache, session, or distributed cache/grid) in a deployment where the advice method's name or parameter types have changed since serialization, or the declaring class is a different version.","commonSituations":"Serializing Spring advice across application restarts or nodes after refactoring the aspect; version skew between the serializing and deserializing JVM (different aspect class versions); hot redeploy where the aspect class changed.","solutions":["Keep the aspect method name and parameter types stable across versions that must deserialize each other's data.","Clear the serialized advice cache/store after refactoring an aspect so stale entries are not deserialized.","Avoid serializing advice objects (or the proxies that reference them); prefer rebuilding them from the context per node.","Ensure the same aspect class version (same jar) is on both ends of serialization."],"exampleFix":"// before: serialize an AspectJ advice into a distributed cache, then rename the advice method\ncache.put(\"advice\", aspectJAdvice); // later: advice method renamed to logEvent()\n// deserialization fails: \"Failed to find advice method on deserialization\"\n// after: clear cached serialized advice after the refactor, or keep method name stable\ncache.invalidate(\"advice\"); // then let the new context rebuild it","handlingStrategy":"try-catch","validationCode":"// Before deserializing, confirm the advice method still exists on the declaring class.\ntry {\n    declaringClass.getMethod(methodName, parameterTypes);\n} catch (NoSuchMethodException e) {\n    throw new IllegalStateException(\n        \"Cached advice refers to missing method \" + methodName + \" on \" + declaringClass, e);\n}","typeGuard":null,"tryCatchPattern":"try (ObjectInputStream in = new ObjectInputStream(bytes)) {\n    AbstractAspectJAdvice advice = (AbstractAspectJAdvice) in.readObject();\n} catch (IllegalStateException ex) {\n    if (ex.getMessage().equals(\"Failed to find advice method on deserialization\")) {\n        // discard the stale serialized advice and rebuild from the current context\n        advice = rebuildAdviceFromContext();\n    } else { throw ex; }\n}","preventionTips":["Keep advice method names and parameter types stable across serialized-data-compatible versions.","Invalidate serialized advice caches/stores after refactoring an aspect.","Prefer rebuilding advice from the ApplicationContext per node over serializing it.","Ensure the same aspect jar version exists on all nodes that share serialized advice."],"tags":["spring-aop","aspectj","serialization","deserialization","versioning"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}