spring-projects/spring-framework · error · AopConfigException

Cannot remove Advisor: Configuration is frozen.

Error message

Cannot remove Advisor: Configuration is frozen.

What it means

Thrown by AdvisedSupport.removeAdvisor(int) when isFrozen() returns true. A frozen AdvisedSupport cannot have its advisor list mutated; freezing is used by the framework (e.g. after proxy creation in optimized or frozen mode) to lock the advisor chain for performance and correctness. Any runtime attempt to remove an advisor from a frozen configuration is rejected.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java:330

		addAdvisorInternal(pos, advisor);
	}

	@Override
	public boolean removeAdvisor(Advisor advisor) {
		int index = indexOf(advisor);
		if (index == -1) {
			return false;
		}
		else {
			removeAdvisor(index);
			return true;
		}
	}

	@Override
	public void removeAdvisor(int index) throws AopConfigException {
		if (isFrozen()) {
			throw new AopConfigException("Cannot remove Advisor: Configuration is frozen.");
		}
		if (index < 0 || index > this.advisors.size() - 1) {
			throw new AopConfigException("Advisor index " + index + " is out of bounds: " +
					"This configuration only has " + this.advisors.size() + " advisors.");
		}

		Advisor advisor = this.advisors.remove(index);
		if (advisor instanceof IntroductionAdvisor introductionAdvisor) {
			// We need to remove introduction interfaces.
			for (Class<?> ifc : introductionAdvisor.getInterfaces()) {
				removeInterface(ifc);
			}
		}

		adviceChanged();
	}

	@Override

View on GitHub (pinned to e8729d0438)

Solutions

  1. Do not freeze the configuration if runtime advisor mutation is required: call proxyFactory.setFrozen(false) (the default) before getProxy().
  2. Build a new ProxyFactory and create a fresh proxy with the desired advisor set instead of mutating the frozen one.
  3. If you need dynamic advisors, use addAdvice at runtime only on non-frozen proxies or restructure to use a PointcutAdvisor with a dynamic pointcut.

Example fix

// before
ProxyFactory pf = new ProxyFactory(target);
pf.setFrozen(true);
pf.addAdvice(advice);
Object proxy = pf.getProxy();
((Advised) proxy).removeAdvisor(0);  // throws

// after
ProxyFactory pf = new ProxyFactory(target);
// omit setFrozen(true) so the proxy stays mutable
pf.addAdvice(advice);
Object proxy = pf.getProxy();
((Advised) proxy).removeAdvisor(0);  // ok
Defensive patterns

Strategy: validation

Validate before calling

Advised advised = (Advised) proxy;
if (advised.isFrozen()) {
  throw new IllegalStateException(
    "Cannot remove advisor: proxy config is frozen; rebuild the proxy with frozen=false");
}
((Advised) proxy).removeAdvisor(index);

Try / catch

try {
  advised.removeAdvisor(index);
} catch (AopConfigException ex) {
  if (ex.getMessage().contains("frozen")) {
    // rebuild a fresh proxy with the desired advisor set
  } else throw ex;
}

Prevention

When it happens

Trigger: Calling advised.removeAdvisor(i) on a proxy whose ProxyConfig had setFrozen(true); calling it on an already-constructed proxy where the framework froze the config internally; calling on a frozen prototype snapshot obtained from getConfigurationOnlyCopy().

Common situations: User code that dynamically reconfigures advisors at runtime against a proxy created with frozen=true; AOT/native compilation scenarios where configs are frozen; calling Advised methods after the proxy has been built with optimize=true (which often implies frozen).

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/30559adceb3d4a0a.json. Report an issue: GitHub.