apache/dubbo · error · IllegalArgumentException

SPI annotation not found for class: ${type.getName()}

Error message

SPI annotation not found for class: ${type.getName()}

What it means

ScopeModelUtil.getDefaultScopeModel() reads the @SPI annotation on the given type to determine which scope (FRAMEWORK/APPLICATION/MODULE) the default model should be. If the type is not annotated with @SPI, there is no scope metadata to read and Dubbo refuses to guess — the class is not a Dubbo extension point. The same check exists in getExtensionLoader() (error 372).

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java:34

 */
package org.apache.dubbo.rpc.model;

import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;

public class ScopeModelUtil {

    public static <T> ScopeModel getOrDefault(ScopeModel scopeModel, Class<T> type) {
        if (scopeModel != null) {
            return scopeModel;
        }
        return getDefaultScopeModel(type);
    }

    private static <T> ScopeModel getDefaultScopeModel(Class<T> type) {
        SPI spi = type.getAnnotation(SPI.class);
        if (spi == null) {
            throw new IllegalArgumentException("SPI annotation not found for class: " + type.getName());
        }
        switch (spi.scope()) {
            case FRAMEWORK:
                return FrameworkModel.defaultModel();
            case APPLICATION:
                return ApplicationModel.defaultModel();
            case MODULE:
                return ApplicationModel.defaultModel().getDefaultModule();
            default:
                throw new IllegalStateException("Unable to get default scope model for type: " + type.getName());
        }
    }

    public static ModuleModel getModuleModel(ScopeModel scopeModel) {
        if (scopeModel == null) {
            return ApplicationModel.defaultModel().getDefaultModule();
        }
        if (scopeModel instanceof ModuleModel) {

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Pass an actual Dubbo SPI extension type — a class/interface annotated with @SPI (e.g. Protocol.class, Serialization.class).
  2. If this is your own extension point, add `@SPI` (with a default value) to the interface.
  3. Avoid calling ScopeModelUtil.getOrDefault with null scopeModel unless you are certain the type carries @SPI; instead pass an explicit ScopeModel.
  4. Double-check the class import — make sure you are passing the Dubbo SPI interface, not its impl class or a config class.

Example fix

// before (throws: HelloService has no @SPI)
ScopeModel sm = ScopeModelUtil.getOrDefault(null, HelloService.class);

// after (pass an explicit scope, or a real @SPI type)
ScopeModel sm = ScopeModelUtil.getOrDefault(applicationModel, HelloService.class);
// or, for an extension:
ScopeModel sm = ScopeModelUtil.getOrDefault(null, Protocol.class); // Protocol is @SPI
Defensive patterns

Strategy: validation

Validate before calling

if (type.getAnnotation(SPI.class) == null) {
    throw new IllegalArgumentException("Not an @SPI type: " + type.getName()
        + " — pass a Dubbo extension interface or an explicit ScopeModel");
}
ScopeModel sm = ScopeModelUtil.getOrDefault(scopeModel, type);

Type guard

static boolean isSpiType(Class<?> type) {
    return type != null && type.isInterface() && type.getAnnotation(SPI.class) != null;
}

Prevention

When it happens

Trigger: Calling ScopeModelUtil.getOrDefault(null, SomeClass.class) or indirectly via a path that resolves the default scope model, where SomeClass is not annotated with @org.apache.dubbo.common.extension.SPI. Common when an internal helper resolves a default model for a plain interface or a class that should have been an SPI but isn't.

Common situations: Passing a non-extension interface (a plain business interface or a config class) where an SPI extension type is expected. Custom integrations that wrap Dubbo SPI resolution and forward arbitrary classes. Forgetting the @SPI annotation on a hand-written extension interface. Version mismatches where an interface lost its @SPI annotation.

Related errors


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