apache/dubbo · error · IllegalStateException
Adaptive Extension already exists (Extension ${type})!
Error message
Adaptive Extension already exists (Extension ${type})! What it means
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.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java:672
throw new IllegalStateException("Input type " + clazz + " doesn't implement the Extension " + type);
}
if (clazz.isInterface()) {
throw new IllegalStateException("Input type " + clazz + " can't be interface!");
}
if (!clazz.isAnnotationPresent(Adaptive.class)) {
if (StringUtils.isBlank(name)) {
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
}
if (cachedClasses.get().containsKey(name)) {
throw new IllegalStateException("Extension name " + name + " already exists (Extension " + type + ")!");
}
cachedNames.put(clazz, name);
cachedClasses.get().put(name, clazz);
} else {
if (cachedAdaptiveClass != null) {
throw new IllegalStateException("Adaptive Extension already exists (Extension " + type + ")!");
}
cachedAdaptiveClass = clazz;
}
}
/**
* Replace the existing extension via API
*
* @param name extension name
* @param clazz extension class
* @throws IllegalStateException when extension to be placed doesn't exist
* @deprecated not recommended any longer, and use only when test
*/
@Deprecated
public void replaceExtension(String name, Class<?> clazz) {
checkDestroyed();
getExtensionClasses(); // load classesView on GitHub (pinned to 3a3043227f)
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.
Example fix
// before — adaptive class already exists
loader.addExtension("myAdaptive", MyAdaptiveClass.class); // @Adaptive on MyAdaptiveClass
// after — replace instead of add, or remove @Adaptive
loader.replaceExtension(null, MyAdaptiveClass.class); // replaces existing adaptive
// or: remove @Adaptive annotation from MyAdaptiveClass and register normally Defensive patterns
Strategy: validation
Validate before calling
if (clazz.isAnnotationPresent(Adaptive.class)) {
// check if adaptive class already exists
try {
loader.getAdaptiveExtension(); // will succeed if one exists
// exists — use replaceExtension instead
loader.replaceExtension(null, clazz);
} catch (Exception e) {
// does not exist yet — safe to add
loader.addExtension(null, clazz);
}
} else {
loader.addExtension(name, clazz);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Extension name ${name} already exists (Extension ${type})!
- Adaptive Extension doesn't exist (Extension {})!
- Input type ${clazz} doesn't implement the Extension ${type}
- Input type ${clazz} can't be interface!
- Extension name is blank (Extension ${type})!
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/9e962aadbf2720cb.
Report an issue: GitHub.