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 by readObject (line 696-704) during Java deserialization of an AbstractAspectJAdvice subclass. The method is marked transient (line 100) so on deserialization Spring re-looks-up the advice Method via declaringClass.getMethod(methodName, parameterTypes). If that lookup throws NoSuchMethodException, the aspect's bytecode no longer matches what was serialized.

Solutions

  1. Ensure the aspect class (same fully-qualified name, same method name and parameter types) is on the classpath of the deserializing JVM.
  2. Do not serialize Spring AOP proxies across versions; rebuild the proxy on the receiving side instead.
  3. If the aspect method changed, re-serialize after the change so the methodName/parameterTypes fields match.
  4. Use the same ClassLoader hierarchy on both ends, or avoid serializing advice objects entirely.

Example fix

// before — serializing a proxied bean across a redeploy that renamed the advice method
ObjectOutputStream out = ...; out.writeObject(proxy); // method was 'logBefore'
// redeploy renames method to 'auditBefore' -> deserialization fails

// after — rebuild the proxy on the receiving JVM instead of serializing advice objects
MyService proxy = new AspectJProxyFactory(target).addAspect(auditAspect).getProxy();
Defensive patterns

Strategy: validation

Validate before calling

import java.lang.reflect.Method;

// Before deserializing, confirm the advice method still exists with the same signature.
boolean adviceMethodResolvable(Class<?> declaringClass, String methodName, Class<?>[] paramTypes) {
    try {
        Method m = declaringClass.getMethod(methodName, paramTypes);
        return m != null;
    } catch (NoSuchMethodException e) {
        return false;
    }
}

Type guard

boolean adviceMethodExists(Class<?> declaringClass, String methodName, Class<?>[] paramTypes) {
    try { declaringClass.getMethod(methodName, paramTypes); return true; }
    catch (NoSuchMethodException e) { return false; }
}

Try / catch

try (ObjectInputStream in = new ObjectInputStream(input)) {
    Object proxy = in.readObject();
} catch (IllegalStateException ex) {
    if (ex.getMessage().contains("Failed to find advice method on deserialization")) {
        // aspect method renamed/removed; rebuild the proxy locally instead of deserializing
    } else { throw ex; }
}

Prevention

When it happens

Trigger: Serializing an aspect/advice in one deployment and deserializing in another where the aspect class was renamed, its method was renamed/signature changed, or the class version differs. Also if the declaring class is loaded by a different ClassLoader that does not see the method.

Common situations: Distributing serialized proxies across JVMs (e.g. via Spring HTTP Invoker, RMI, or a cache), redeploying with a refactored aspect, hot-swapping jars without re-serializing, or ClassLoader isolation between the serializer and deserializer.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/bff89e43a6d16c60. Report an issue: GitHub.

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:702

	protected @Nullable JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
		String expression = this.pointcut.getExpression();
		return (expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null);
	}


	@Override
	public String toString() {
		return getClass().getName() + ": advice method [" + this.aspectJAdviceMethod + "]; " +
				"aspect name '" + this.aspectName + "'";
	}

	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);
		}
	}


	/**
	 * MethodMatcher that excludes the specified advice method.
	 * @see AbstractAspectJAdvice#buildSafePointcut()
	 */
	private static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {

		private final Method adviceMethod;

		public AdviceExcludingMethodMatcher(Method adviceMethod) {
			this.adviceMethod = adviceMethod;
		}

		@Override
		public boolean matches(Method method, Class<?> targetClass) {

View on GitHub (pinned to 69bf83ad71)