apache/dubbo · error · IllegalStateException

Input type ${clazz} doesn't implement Extension ${type}

Error message

Input type ${clazz} doesn't implement Extension ${type}

What it means

Thrown by ExtensionLoader.replaceExtension(String name, Class<?> clazz) when the provided class does not implement the SPI interface type. This is the same assignability guard as in addExtension but for the replace path. replaceExtension is marked @Deprecated and intended for test use only.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java:693

            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 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) {

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Ensure the replacement class implements the SPI interface managed by this ExtensionLoader.
  2. Verify you are calling replaceExtension on the correct ExtensionLoader (the right type).
  3. Since replaceExtension is deprecated, prefer addExtension with a unique name or SPI config files.

Example fix

// before — wrong class type
protocolLoader.replaceExtension("dubbo", WrongImpl.class);

// after
class CustomDubboProtocol implements Protocol { ... }
protocolLoader.replaceExtension("dubbo", CustomDubboProtocol.class);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!type.isAssignableFrom(clazz)) {
    throw new IllegalStateException(
        clazz + " must implement " + type.getName());
}
loader.replaceExtension(name, clazz);

Type guard

static boolean implementsSpi(Class<?> implClass, Class<?> spiType) {
    return implClass != null && spiType != null && spiType.isAssignableFrom(implClass);
}

Prevention

When it happens

Trigger: Calling replaceExtension with a class that is not assignable to the SPI interface type. For example, replacing a Protocol extension with a class that only implements Filter. The check uses type.isAssignableFrom(clazz).

Common situations: Developer mistakenly uses the wrong ExtensionLoader instance (for a different SPI type). After refactoring, the replacement class no longer implements the required interface. Copy-paste from addExtension code without adjusting the class.

Related errors


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