{"record":{"id":"f758ec5beb859e92","repo":"spring-projects/spring-framework","slug":"dynamicintroductionadvice-may-only-be-added-as-par","errorCode":null,"errorMessage":"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor","messagePattern":"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java","lineNumber":444,"sourceCode":"\tpublic void addAdvice(Advice advice) throws AopConfigException {\n\t\tint pos = this.advisors.size();\n\t\taddAdvice(pos, advice);\n\t}\n\n\t/**\n\t * Cannot add introductions this way unless the advice implements IntroductionInfo.\n\t */\n\t@Override\n\tpublic void addAdvice(int pos, Advice advice) throws AopConfigException {\n\t\tAssert.notNull(advice, \"Advice must not be null\");\n\t\tif (advice instanceof IntroductionInfo introductionInfo) {\n\t\t\t// We don't need an IntroductionAdvisor for this kind of introduction:\n\t\t\t// It's fully self-describing.\n\t\t\taddAdvisor(pos, new DefaultIntroductionAdvisor(advice, introductionInfo));\n\t\t}\n\t\telse if (advice instanceof DynamicIntroductionAdvice) {\n\t\t\t// We need an IntroductionAdvisor for this kind of introduction.\n\t\t\tthrow new AopConfigException(\"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor\");\n\t\t}\n\t\telse {\n\t\t\taddAdvisor(pos, new DefaultPointcutAdvisor(advice));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean removeAdvice(Advice advice) throws AopConfigException {\n\t\tint index = indexOf(advice);\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","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L426-L462","documentation":"addAdvice(int, Advice) (line 435) handles three branches: IntroductionInfo (self-describing), DynamicIntroductionAdvice, and plain advice. A DynamicIntroductionAdvice (e.g. a per-instance introduction mixin) carries introduction state and must be registered through an IntroductionAdvisor so its interfaces are validated and added. Registering it as plain advice is rejected (line 444).","triggerScenarios":"Passing an instance whose class implements org.springframework.aop.DynamicIntroductionAdvice to addAdvice() directly, instead of wrapping it in an IntroductionAdvisor (e.g. DefaultIntroductionAdvisor).","commonSituations":"Trying to add a DelegatingIntroductionInterceptor or similar mixin via addAdvice(...) rather than addAdvisor(new DefaultIntroductionAdvisor(advice)); mixing up the addAdvice and addAdvisor entry points.","solutions":["Wrap the introduction advice in an IntroductionAdvisor: advised.addAdvisor(new DefaultIntroductionAdvisor(advice, introductionInfo))","If the advice implements IntroductionInfo too, addAdvice can work via that branch - otherwise always use an IntroductionAdvisor","Review the advice type: anything that is a DynamicIntroductionAdvice must go through an advisor"],"exampleFix":"// before\nadvised.addAdvice(myDelegatingIntroductionInterceptor);\n\n// after\nadvised.addAdvisor(new DefaultIntroductionAdvisor(myDelegatingIntroductionInterceptor));","handlingStrategy":"type-guard","validationCode":"if (advice instanceof DynamicIntroductionAdvice) {\n  throw new IllegalStateException(\"Use addAdvisor(new DefaultIntroductionAdvisor(advice)) for introduction advice\");\n}","typeGuard":"private static boolean isPlainAdvice(Advice advice) {\n  return advice != null && !(advice instanceof DynamicIntroductionAdvice);\n}","tryCatchPattern":null,"preventionTips":["Always route DynamicIntroductionAdvice through an IntroductionAdvisor","Check instanceof before addAdvice when the advice source is dynamic"],"tags":["spring-aop","advised","introduction","advisor"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}