spring-projects/spring-framework · error · IllegalArgumentException

Illegal position {pos} in advisor list with size {advisors.s

Error message

Illegal position {pos} in advisor list with size {advisors.size()}

What it means

Thrown by AdvisedSupport.addAdvisorInternal when pos > advisors.size(), i.e. the requested insertion position would leave a gap in the list. Spring uses ArrayList.add(pos, x) which itself would throw IndexOutOfBoundsException; this guard surfaces a clearer message first. Position == size is allowed (append), position > size is not.

Source

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

			adviceChanged();
		}
	}

	private void validateIntroductionAdvisor(IntroductionAdvisor advisor) {
		advisor.validateInterfaces();
		// If the advisor passed validation, we can make the change.
		for (Class<?> ifc : advisor.getInterfaces()) {
			addInterface(ifc);
		}
	}

	private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
		Assert.notNull(advisor, "Advisor must not be null");
		if (isFrozen()) {
			throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
		}
		if (pos > this.advisors.size()) {
			throw new IllegalArgumentException(
					"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
		}
		this.advisors.add(pos, advisor);
		adviceChanged();
	}

	/**
	 * Allows uncontrolled access to the {@link List} of {@link Advisor Advisors}.
	 * <p>Use with care, and remember to {@link #adviceChanged() fire advice changed events}
	 * when making any modifications.
	 */
	protected final List<Advisor> getAdvisorsInternal() {
		return this.advisors;
	}

	@Override
	public void addAdvice(Advice advice) throws AopConfigException {
		int pos = this.advisors.size();

View on GitHub (pinned to e8729d0438)

Solutions

  1. Validate 0 <= pos <= advised.getAdvisorCount() before calling addAdvisor(pos, advisor).
  2. To append, pass pos = advised.getAdvisors().length (== size), which is the permitted boundary.
  3. Recompute the current size immediately before insertion rather than reusing a cached value.

Example fix

// before
int pos = advisors.size() + 1;  // overshoots
advised.addAdvisor(pos, newAdvisor);

// after
int pos = advised.getAdvisors().length;  // append is allowed
advised.addAdvisor(pos, newAdvisor);
Defensive patterns

Strategy: validation

Validate before calling

int size = advised.getAdvisors().length;
if (pos < 0 || pos > size) {
  throw new IllegalArgumentException("pos " + pos + " invalid; size=" + size);
}
advised.addAdvisor(pos, advisor);

Prevention

When it happens

Trigger: Calling addAdvisor(pos, advisor) with pos equal to size+1 or larger; computing a position from a stale advisor count; off-by-one when inserting 'after the last' advisor (using size instead of size-1 is actually correct for append).

Common situations: Caching advisor count, then inserting after external code added/removed advisors; loop bookkeeping errors; passing indexOf()+1 when the advisor wasn't found (indexOf returns -1, +1 = 0 is fine, but indexOf of a missing advisor combined with other math can overshoot).

Related errors


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