{"record":{"id":"9e962aadbf2720cb","repo":"apache/dubbo","slug":"adaptive-extension-already-exists-extension-typ","errorCode":null,"errorMessage":"Adaptive Extension already exists (Extension ${type})!","messagePattern":"Adaptive Extension already exists \\(Extension (.+?)\\)!","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java","lineNumber":672,"sourceCode":"            throw new IllegalStateException(\"Input type \" + clazz + \" doesn't implement the Extension \" + type);\n        }\n        if (clazz.isInterface()) {\n            throw new IllegalStateException(\"Input type \" + clazz + \" can't be interface!\");\n        }\n\n        if (!clazz.isAnnotationPresent(Adaptive.class)) {\n            if (StringUtils.isBlank(name)) {\n                throw new IllegalStateException(\"Extension name is blank (Extension \" + type + \")!\");\n            }\n            if (cachedClasses.get().containsKey(name)) {\n                throw new IllegalStateException(\"Extension name \" + name + \" already exists (Extension \" + type + \")!\");\n            }\n\n            cachedNames.put(clazz, name);\n            cachedClasses.get().put(name, clazz);\n        } else {\n            if (cachedAdaptiveClass != null) {\n                throw new IllegalStateException(\"Adaptive Extension already exists (Extension \" + type + \")!\");\n            }\n\n            cachedAdaptiveClass = clazz;\n        }\n    }\n\n    /**\n     * Replace the existing extension via API\n     *\n     * @param name  extension name\n     * @param clazz extension class\n     * @throws IllegalStateException when extension to be placed doesn't exist\n     * @deprecated not recommended any longer, and use only when test\n     */\n    @Deprecated\n    public void replaceExtension(String name, Class<?> clazz) {\n        checkDestroyed();\n        getExtensionClasses(); // load classes","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java#L654-L690","documentation":"Thrown by ExtensionLoader.addExtension(String name, Class<?> clazz) when the class is annotated @Adaptive but an adaptive class has already been registered or code-generated for this SPI type. Each extension point can have exactly one adaptive implementation — the one selected when no specific name is given at runtime. Attempting to register a second one is rejected.","triggerScenarios":"Calling addExtension with an @Adaptive-annotated class when Dubbo already code-generated an adaptive class (the default behavior for SPI interfaces with @Adaptive methods) or when a previous addExtension already set the adaptive class.","commonSituations":"Dubbo auto-generates an adaptive class for SPI interfaces that have @Adaptive methods; calling addExtension with a hand-written @Adaptive class then conflicts. A test attempts to register a custom adaptive class without first clearing the existing one.","solutions":["Use replaceExtension(name, clazz) if you need to swap the adaptive class at runtime.","If you are in a test, destroy and recreate the ExtensionLoader/ScopeModel before registering a new adaptive class.","Avoid providing a hand-written @Adaptive class when Dubbo already generates one — let code generation handle it.","Remove @Adaptive from custom implementations unless you specifically need manual adaptive control."],"exampleFix":"// before — adaptive class already exists\nloader.addExtension(\"myAdaptive\", MyAdaptiveClass.class); // @Adaptive on MyAdaptiveClass\n\n// after — replace instead of add, or remove @Adaptive\nloader.replaceExtension(null, MyAdaptiveClass.class); // replaces existing adaptive\n// or: remove @Adaptive annotation from MyAdaptiveClass and register normally","handlingStrategy":"validation","validationCode":"if (clazz.isAnnotationPresent(Adaptive.class)) {\n    // check if adaptive class already exists\n    try {\n        loader.getAdaptiveExtension(); // will succeed if one exists\n        // exists — use replaceExtension instead\n        loader.replaceExtension(null, clazz);\n    } catch (Exception e) {\n        // does not exist yet — safe to add\n        loader.addExtension(null, clazz);\n    }\n} else {\n    loader.addExtension(name, clazz);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Understand that Dubbo auto-generates adaptive classes for SPI interfaces with @Adaptive methods.","Only provide hand-written @Adaptive classes when you need full control — and use replaceExtension to update.","Avoid registering multiple @Adaptive classes for the same SPI type."],"tags":["dubbo-spi","adaptive","duplicate","registration","extension-system"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}