apache/dubbo · error · IllegalStateException

Extension name is blank

Error message

Extension name is blank (Extension {})!

What it means

Thrown by ExtensionLoader.replaceExtension(String name, Class<?> clazz) when the class is not @Adaptive and the name is null or blank. Non-adaptive extension replacements require a non-blank name to identify which existing extension to replace. Only adaptive class replacements can omit the name.

Solutions

  1. Provide the exact existing extension name as the first argument.
  2. If the name comes from config, validate it is non-blank before calling replaceExtension.
  3. If replacing an adaptive class, annotate the replacement with @Adaptive.

Example fix

// before
loader.replaceExtension(null, MyImpl.class);

// after
loader.replaceExtension("dubbo", MyImpl.class);
Defensive patterns

Strategy: validation

Validate before calling

if (!clazz.isAnnotationPresent(Adaptive.class) && StringUtils.isBlank(name)) {
    throw new IllegalStateException(
        "Extension name required for non-adaptive replacement of type " + type);
}
loader.replaceExtension(name, clazz);

Prevention

When it happens

Trigger: Calling replaceExtension(null, ConcreteImpl.class) or replaceExtension("", ConcreteImpl.class) where ConcreteImpl is not annotated @Adaptive. The name identifies the existing extension entry to overwrite, so a blank name makes the replacement target ambiguous.

Common situations: Developer wraps replaceExtension in a helper that passes a null name when one is not available. A computed name from config resolves to null/empty. Test code uses a placeholder null and forgets to set the actual name.

Related errors


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

Appendix: source

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

     * @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) {
                throw new IllegalStateException("Adaptive Extension doesn't exist (Extension " + type + ")!");
            }

            cachedAdaptiveClass = clazz;
            cachedAdaptiveInstance.set(null);
        }
    }

View on GitHub (pinned to 3a3043227f)