{"record":{"id":"14247870501ed199","repo":"apache/dubbo","slug":"more-than-1-adaptive-class-found","errorCode":null,"errorMessage":"More than 1 adaptive class found: {}, {}","messagePattern":"More than 1 adaptive class found: (.+?), (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java","lineNumber":1388,"sourceCode":"        if (activate != null) {\n            cachedActivates.put(name, activate);\n        } else if (Dubbo2CompactUtils.isEnabled() && Dubbo2ActivateUtils.isActivateLoaded()) {\n            // support com.alibaba.dubbo.common.extension.Activate\n            Annotation oldActivate = clazz.getAnnotation(Dubbo2ActivateUtils.getActivateClass());\n            if (oldActivate != null) {\n                cachedActivates.put(name, oldActivate);\n            }\n        }\n    }\n\n    /**\n     * cache Adaptive class which is annotated with <code>Adaptive</code>\n     */\n    private void cacheAdaptiveClass(Class<?> clazz, boolean overridden) {\n        if (cachedAdaptiveClass == null || overridden) {\n            cachedAdaptiveClass = clazz;\n        } else if (!cachedAdaptiveClass.equals(clazz)) {\n            throw new IllegalStateException(\n                    \"More than 1 adaptive class found: \" + cachedAdaptiveClass.getName() + \", \" + clazz.getName());\n        }\n    }\n\n    /**\n     * cache wrapper class\n     * <p>\n     * like: ProtocolFilterWrapper, ProtocolListenerWrapper\n     */\n    private void cacheWrapperClass(Class<?> clazz) {\n        if (cachedWrapperClasses == null) {\n            cachedWrapperClasses = new ConcurrentHashSet<>();\n        }\n        cachedWrapperClasses.add(clazz);\n    }\n\n    /**\n     * test if clazz is a wrapper class","sourceCodeStart":1370,"sourceCodeEnd":1406,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java#L1370-L1406","documentation":"Thrown by cacheAdaptiveClass() when a second, different class annotated with @Adaptive is encountered for the same SPI interface while loading SPI configs. Dubbo permits at most one @Adaptive-annotated implementation per SPI interface; if two distinct classes claim @Adaptive, the second registration (without overridden=true) fails. The first cached adaptive class wins.","triggerScenarios":"Two jars each ship a class annotated with @Adaptive implementing the same SPI interface. loadClass() routes @Adaptive-annotated classes to cacheAdaptiveClass(), and if cachedAdaptiveClass is already set to a different class, the guard throws. Common with custom overrides that forget to remove the original adaptive class.","commonSituations":"A custom jar provides its own @Adaptive implementation of an interface that already has a built-in adaptive class (e.g., dubbo's own Protocol$Adaptive-style annotated class); merging modules that each define an adaptive implementation; a shading/relocation that duplicates the adaptive class.","solutions":["Ensure only one class annotated with @Adaptive implements the SPI interface across the entire classpath.","If overriding the built-in adaptive class, exclude the original jar/config or use the overridden loading path so the later one replaces the earlier.","Run 'grep -r @Adaptive' across your dependencies or use jar scanning to find both adaptive classes and remove the unintended one."],"exampleFix":"// before: two classes\n// jar1: @Adaptive public class AProtocol implements Protocol {}\n// jar2: @Adaptive public class BProtocol implements Protocol {}\n// throws [149]\n\n// after: keep only one, remove @Adaptive from the other or delete the class\n// jar1: @Adaptive public class AProtocol implements Protocol {}","handlingStrategy":"validation","validationCode":"// Scan classpath for multiple @Adaptive classes on the same interface\nint count = 0;\nfor (Class<?> c : scanImplementations(iface)) {\n    if (c.isAnnotationPresent(Adaptive.class)) count++;\n}\nif (count > 1) throw new IllegalStateException(\"Multiple @Adaptive for \" + iface);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure at most one @Adaptive-annotated implementation exists per SPI interface on the classpath.","When overriding the built-in adaptive class, exclude the original artifact or use the overridden loading strategy.","Scan dependencies for stray @Adaptive classes during integration testing."],"tags":["dubbo-spi","adaptive-extension","duplicate","classpath-conflict","extension-loader"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}