spring-projects/spring-framework · error · IllegalStateException
Failed to find advice method on deserialization
Error message
Failed to find advice method on deserialization
What it means
Thrown as an IllegalStateException from InstantiationModelAwarePointcutAdvisorImpl.readObject() during deserialization of a serialized aspect advisor. On readObject, Spring re-resolves the advice Method via declaringClass.getMethod(methodName, parameterTypes); a NoSuchMethodException means the advice method no longer exists on the declaring class (renamed, signature changed, removed, or the class was replaced) between serialization and deserialization.
Solutions
- Ensure the aspect class bytecode (method name and parameter types) is identical on both the serializing and deserializing sides; align application versions.
- Avoid serializing Spring AOP proxies; serialize the underlying data and re-obtain the proxied bean from the target context.
- If proxies must be serialized, mark the relevant advice methods stable (do not rename/change signatures across releases).
Example fix
// before
// Node A (v1): aspect has log(java.lang.String)
// Node B (v2): aspect renamed method to logMessage(java.lang.String)
// deserializing a proxy from A on B throws
// after
// Keep the advice method signature stable across versions:
@AfterReturning("execution(* com.example..*.*(..))")
public void log(JoinPoint jp) { ... } // unchanged name+params on both nodes Defensive patterns
Strategy: validation
Validate before calling
// Before deserializing a proxy, verify the advice method still exists:
public static boolean adviceMethodExists(Class<?> declaringClass, String methodName, Class<?>[] paramTypes) {
try {
declaringClass.getMethod(methodName, paramTypes);
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
if (!adviceMethodExists(aspectClass, "log", new Class<?>[]{JoinPoint.class})) {
throw new IllegalStateException("Aspect advice method missing; cannot deserialize proxy safely");
} Try / catch
try (ObjectInputStream ois = new ObjectInputStream(in)) {
Object proxy = ois.readObject();
} catch (IllegalStateException ex) {
if (ex.getCause() instanceof NoSuchMethodException) {
// rebuild the proxy locally instead of deserializing
} else throw ex;
} Prevention
- Avoid serializing Spring AOP proxies; serialize DTOs and re-resolve beans on the other side.
- Keep advice method names and parameter types stable across releases that exchange serialized proxies.
- Pin application versions on nodes that share serialized session/cache data containing proxies.
When it happens
Trigger: Serializing a proxied object whose advisor chain contains an InstantiationModelAwarePointcutAdvisorImpl, then deserializing it in a JVM/version where the aspect class's advice method has been renamed, had its parameter list changed, or was deleted. Also possible with classloader differences that resolve declaringClass to a different version.
Common situations: Distributing a serialized proxy to a node running a different application version; HTTP session or cache replication of proxied beans across nodes with mismatched aspect bytecode; hot-reloading that changes advice method signatures while a proxy is cached.
Related errors
- Failed to find advice method on deserialization
- Advice method [ ] requires arguments to be bound by name…
- Advice must be declared inside an aspect type: Offending…
- An advice method can never be a constructor
- is not a valid AspectJ annotation
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/9478f401ecb676db.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java:246
this.isBeforeAdvice = true;
this.isAfterAdvice = false;
}
case AtAfter, AtAfterReturning, AtAfterThrowing -> {
this.isBeforeAdvice = false;
this.isAfterAdvice = true;
}
}
}
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
/**
* Pointcut implementation that changes its behavior when the advice is instantiated.
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
* if it does not at first match statically.
*/
private static final class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
View on GitHub (pinned to 69bf83ad71)