{"record":{"id":"06a95212448ca367","repo":"spring-projects/spring-framework","slug":"illegal-position-in-advisor-list-with-size","errorCode":null,"errorMessage":"Illegal position {} in advisor list with size {}","messagePattern":"Illegal position (.+?) in advisor list with size (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java","lineNumber":409,"sourceCode":"\t\t\tadviceChanged();\n\t\t}\n\t}\n\n\tprivate void validateIntroductionAdvisor(IntroductionAdvisor advisor) {\n\t\tadvisor.validateInterfaces();\n\t\t// If the advisor passed validation, we can make the change.\n\t\tfor (Class<?> ifc : advisor.getInterfaces()) {\n\t\t\taddInterface(ifc);\n\t\t}\n\t}\n\n\tprivate void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {\n\t\tAssert.notNull(advisor, \"Advisor must not be null\");\n\t\tif (isFrozen()) {\n\t\t\tthrow new AopConfigException(\"Cannot add advisor: Configuration is frozen.\");\n\t\t}\n\t\tif (pos > this.advisors.size()) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Illegal position \" + pos + \" in advisor list with size \" + this.advisors.size());\n\t\t}\n\t\tthis.advisors.add(pos, advisor);\n\t\tadviceChanged();\n\t}\n\n\t/**\n\t * Allows uncontrolled access to the {@link List} of {@link Advisor Advisors}.\n\t * <p>Use with care, and remember to {@link #adviceChanged() fire advice changed events}\n\t * when making any modifications.\n\t */\n\tprotected final List<Advisor> getAdvisorsInternal() {\n\t\treturn this.advisors;\n\t}\n\n\t@Override\n\tpublic void addAdvice(Advice advice) throws AopConfigException {\n\t\tint pos = this.advisors.size();","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L391-L427","documentation":"addAdvisorInternal() (line 408) validates that the requested insertion position does not exceed the current advisor list size. Because List.add(pos, x) only allows 0..size, a position beyond size is rejected with the current size reported.","triggerScenarios":"Calling addAdvisor(pos, advisor) where pos > advisors.size(); computing a position from an external/stale count and passing an out-of-range value.","commonSituations":"Off-by-one when inserting at the end (using size+1 instead of size); using an index derived from a different snapshot of the advisor list; appending then inserting at a position computed before the append.","solutions":["To append, call addAdvisor(advisor) (no index) which always uses the correct size","If you must insert at a position, clamp/validate: int pos = Math.min(requested, advised.getAdvisorCount());","Recompute the index from getAdvisorCount() immediately before the call"],"exampleFix":"// before\nadvised.addAdvisor(advised.getAdvisorCount() + 1, advisor);\n\n// after\nadvised.addAdvisor(advisor);  // append at end safely","handlingStrategy":"validation","validationCode":"int size = advised.getAdvisorCount();\nif (pos < 0 || pos > size) {\n  throw new IndexOutOfBoundsException(\"Illegal position \" + pos + \" (size \" + size + \")\");\n}\nadvised.addAdvisor(pos, advisor);","typeGuard":"private static boolean validInsertPosition(AdvisedSupport a, int pos) {\n  return a != null && pos >= 0 && pos <= a.getAdvisorCount();\n}","tryCatchPattern":null,"preventionTips":["Use the no-index addAdvisor(advisor) to append safely","Clamp positions to 0..size before calling the positional overload"],"tags":["spring-aop","advised","advisor","index-out-of-bounds"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}