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

  1. Ensure the aspect class bytecode (method name and parameter types) is identical on both the serializing and deserializing sides; align application versions.
  2. Avoid serializing Spring AOP proxies; serialize the underlying data and re-obtain the proxied bean from the target context.
  3. 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

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


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)