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

  1. Use addExtension instead of replaceExtension if the extension does not yet exist.
  2. Check loader.getSupportedExtensions() to list valid existing names before calling replaceExtension.
  3. 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

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


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/854f5b748293feb0. Report an issue: GitHub.