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
- Validate 0 <= pos <= advised.getAdvisorCount() before calling addAdvisor(pos, advisor).
- To append, pass pos = advised.getAdvisors().length (== size), which is the permitted boundary.
- 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
- Treat size as the append boundary (allowed) and size+1 as invalid.
- Compute the current size right before insertion; never cache it.
- For 'insert last', prefer addAdvisor(advisor) which appends internally.
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
- Advisor index {index} is out of bounds: This configuration o
- Class '{}' is not an @AspectJ aspect
- Cannot remove Advisor: Configuration is frozen.
- Cannot add advisor: Configuration is frozen.
- Both 'constructorArgs' and 'constructorArgTypes' need to be
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/491a0d893ded84fa.json.
Report an issue: GitHub.