spring-projects/spring-framework · error · AopConfigException

Advisor index {index} is out of bounds: This configuration o

Error message

Advisor index {index} is out of bounds: This configuration only has {advisors.size()} advisors.

What it means

Thrown by AdvisedSupport.removeAdvisor(int) when the supplied index is outside [0, advisors.size()-1]. Spring guards array bounds here to produce a descriptive AopConfigException rather than an IndexOutOfBoundsException deep in the ArrayList. It runs only after the frozen check, so this is a pure input-validation error on a mutable config.

Source

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

	@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
	public int indexOf(Advisor advisor) {
		Assert.notNull(advisor, "Advisor must not be null");
		return this.advisors.indexOf(advisor);

View on GitHub (pinned to e8729d0438)

Solutions

  1. Check 0 <= index < advised.getAdvisors().length immediately before calling removeAdvisor(index).
  2. Prefer removeAdvisor(theAdvisorInstance) over index-based removal to avoid stale indices.
  3. When removing in a loop, iterate backwards or rebuild the advisor list rather than shifting indices.

Example fix

// before
Advisor[] advisors = ((Advised) proxy).getAdvisors();
((Advised) proxy).removeAdvisor(advisors.length);  // off-by-one

// after
Advisor[] advisors = ((Advised) proxy).getAdvisors();
if (advisors.length > 0) {
  ((Advised) proxy).removeAdvisor(advisors.length - 1);
}
Defensive patterns

Strategy: validation

Validate before calling

Advised advised = (Advised) proxy;
int index = ...;
if (index < 0 || index >= advised.getAdvisors().length) {
  throw new IndexOutOfBoundsException(
    "advisor index " + index + " out of bounds for " + advised.getAdvisors().length);
}
advised.removeAdvisor(index);

Prevention

When it happens

Trigger: Calling removeAdvisor(n) where n is negative, equals size, or exceeds size; computing an index from indexOf() but acting on a stale advisor list; loop off-by-one when iterating advisors and removing by position.

Common situations: Caching an advisor index and later removing by that index after the list changed; off-by-one errors in cleanup loops; calling removeAdvisor(advisors.size()) expecting 'remove last'.

Related errors


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