apache/dubbo · error · IllegalStateException
Extension name {} doesn't exist (Extension {})!
Error message
Extension name {} doesn't exist (Extension {})! What it means
Thrown by ExtensionLoader.replaceExtension(String name, Class<?> clazz) when the provided name does not exist in cachedClasses. Unlike addExtension (which rejects existing names), replaceExtension requires the name to ALREADY exist — you can only replace something that is currently registered. This guard uses !cachedClasses.get().containsKey(name).
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java:704
*/
@Deprecated
public void replaceExtension(String name, Class<?> clazz) {
checkDestroyed();
getExtensionClasses(); // load classes
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Input type " + clazz + " doesn't implement 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 + " doesn't exist (Extension " + type + ")!");
}
cachedNames.put(clazz, name);
cachedClasses.get().put(name, clazz);
cachedInstances.remove(name);
} else {
if (cachedAdaptiveClass == null) {
throw new IllegalStateException("Adaptive Extension doesn't exist (Extension " + type + ")!");
}
cachedAdaptiveClass = clazz;
cachedAdaptiveInstance.set(null);
}
}
@SuppressWarnings("unchecked")
public T getAdaptiveExtension() {
checkDestroyed();View on GitHub (pinned to 3a3043227f)
Solutions
- Use addExtension instead of replaceExtension if the extension does not yet exist.
- Check loader.getSupportedExtensions() to list valid existing names before calling replaceExtension.
- Verify the name spelling against the SPI configuration files.
Example fix
// before — name doesn't exist yet
loader.replaceExtension("customProto", CustomProtocol.class); // not registered
// after — use addExtension for new, replaceExtension for existing
if (loader.hasExtension("customProto")) {
loader.replaceExtension("customProto", CustomProtocol.class);
} else {
loader.addExtension("customProto", CustomProtocol.class);
} Defensive patterns
Strategy: validation
Validate before calling
if (!loader.hasExtension(name)) {
// extension doesn't exist — use addExtension instead
loader.addExtension(name, clazz);
} else {
loader.replaceExtension(name, clazz);
} Prevention
- Check loader.hasExtension(name) before calling replaceExtension.
- Use addExtension for new extensions and replaceExtension for existing ones.
- Call loader.getSupportedExtensions() to see valid names before attempting replacement.
When it happens
Trigger: Calling replaceExtension with a name that was never registered, is misspelled, or belongs to a different SPI type. For example, replaceExtension("myProto", ...) when only 'dubbo', 'rest', etc. exist for Protocol.
Common situations: Developer tries to replace a custom extension that was never added (should use addExtension instead). Typo in the extension name. The extension was loaded under a different name than expected. The SPI config file providing that extension was not on the classpath, so it was never loaded.
Related errors
- Adaptive Extension doesn't exist (Extension {})!
- Input type ${clazz} doesn't implement Extension ${type}
- Extension name is blank (Extension {})!
- Not find extension: ${name}
- Input type ${clazz} doesn't implement the Extension ${type}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/854f5b748293feb0.
Report an issue: GitHub.