{"record":{"id":"30559adceb3d4a0a","repo":"spring-projects/spring-framework","slug":"cannot-remove-advisor-configuration-is-frozen","errorCode":null,"errorMessage":"Cannot remove Advisor: Configuration is frozen.","messagePattern":"Cannot remove Advisor: Configuration is frozen\\.","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java","lineNumber":330,"sourceCode":"\t\taddAdvisorInternal(pos, advisor);\n\t}\n\n\t@Override\n\tpublic boolean removeAdvisor(Advisor advisor) {\n\t\tint index = indexOf(advisor);\n\t\tif (index == -1) {\n\t\t\treturn false;\n\t\t}\n\t\telse {\n\t\t\tremoveAdvisor(index);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeAdvisor(int index) throws AopConfigException {\n\t\tif (isFrozen()) {\n\t\t\tthrow new AopConfigException(\"Cannot remove Advisor: Configuration is frozen.\");\n\t\t}\n\t\tif (index < 0 || index > this.advisors.size() - 1) {\n\t\t\tthrow new AopConfigException(\"Advisor index \" + index + \" is out of bounds: \" +\n\t\t\t\t\t\"This configuration only has \" + this.advisors.size() + \" advisors.\");\n\t\t}\n\n\t\tAdvisor advisor = this.advisors.remove(index);\n\t\tif (advisor instanceof IntroductionAdvisor introductionAdvisor) {\n\t\t\t// We need to remove introduction interfaces.\n\t\t\tfor (Class<?> ifc : introductionAdvisor.getInterfaces()) {\n\t\t\t\tremoveInterface(ifc);\n\t\t\t}\n\t\t}\n\n\t\tadviceChanged();\n\t}\n\n\t@Override","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L312-L348","documentation":"AdvisedSupport.removeAdvisor(int) (line 328) refuses to mutate its advisor list when the configuration is frozen (isFrozen() true, line 329). A frozen Advised is immutable - typically because the proxy has been built and optimized, or setFrozen(true) was explicitly called. Removal would break cached interceptor chains.","triggerScenarios":"Calling removeAdvisor(index) or removeAdvisor(advisor) (which delegates to removeAdvisor(index)) on an Advised/AdvisedSupport whose frozen flag is set.","commonSituations":"Manually calling setFrozen(true) for optimization then trying to mutate; holding a reference to an Advised proxy and attempting runtime advisor removal after the proxy was created with optimization/frozen; AdvisedSupport snapshots used internally by already-built proxies.","solutions":["Do not call setFrozen(true) if you need to mutate the advisor chain at runtime","If the proxy is already created and frozen, rebuild a new ProxyFactory from the configuration instead of mutating in place","Check ((Advised) proxy).isFrozen() before attempting removal and handle accordingly"],"exampleFix":"// before\nAdvisedSupport advised = ...;\nadvised.setFrozen(true);\nadvised.removeAdvisor(0);\n\n// after\nAdvisedSupport advised = ...;\nadvised.setFrozen(false);\nadvised.removeAdvisor(0);","handlingStrategy":"validation","validationCode":"if (advised.isFrozen()) {\n  throw new IllegalStateException(\"Cannot remove advisor: configuration is frozen\");\n}\nadvised.removeAdvisor(index);","typeGuard":"private static boolean canRemoveAdvisor(AdvisedSupport a) {\n  return a != null && !a.isFrozen();\n}","tryCatchPattern":null,"preventionTips":["Do not setFrozen(true) if you need to mutate advisors at runtime","Always check isFrozen() before removeAdvisor calls on user-facing APIs"],"tags":["spring-aop","advised","frozen","advisor"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}