apache/dubbo · error · ScopeBeanException

unable to determine bean class from factory's superclass or

Error message

unable to determine bean class from factory's superclass or interface

What it means

Thrown by ScopeBeanFactory.registerBeanFactory(String, Supplier) when TypeUtils.getSuperGenericType(factory.getClass(), 0) returns null, meaning the bean type produced by the Supplier cannot be inferred from the factory's generic supertype. Dubbo needs the produced type to build a BeanDefinition, so it refuses to register an untyped factory. This happens when the Supplier is a raw type, a method reference/lambda whose target type is erased, or a class whose generic parameter is not reified.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java:110

    }

    public <T> void registerBeanDefinition(Class<T> clazz) {
        registerBeanDefinition(null, clazz);
    }

    public <T> void registerBeanDefinition(String name, Class<T> clazz) {
        registeredBeanDefinitions.add(new BeanDefinition<>(name, clazz));
    }

    public <T> void registerBeanFactory(Supplier<T> factory) {
        registerBeanFactory(null, factory);
    }

    @SuppressWarnings("unchecked")
    public <T> void registerBeanFactory(String name, Supplier<T> factory) {
        Class<T> clazz = (Class<T>) TypeUtils.getSuperGenericType(factory.getClass(), 0);
        if (clazz == null) {
            throw new ScopeBeanException("unable to determine bean class from factory's superclass or interface");
        }
        registeredBeanDefinitions.add(new BeanDefinition<>(name, clazz, factory));
    }

    private <T> T createAndRegisterBean(String name, Class<T> clazz) {
        checkDestroyed();
        T instance = getBean(name, clazz);
        if (instance != null) {
            throw new ScopeBeanException(
                    "already exists bean with same name and type, name=" + name + ", type=" + clazz.getName());
        }
        try {
            instance = instantiationStrategy.instantiate(clazz);
        } catch (Throwable e) {
            throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName(), e);
        }
        registerBean(name, instance);
        return instance;

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Register the bean by class instead: registerBeanDefinition(name, MyBean.class) or registerBean(name, MyBean.class).
  2. Provide the type explicitly by using the overload that lets Dubbo infer it: subclass Supplier with a reified generic, e.g. anonymous new Supplier<MyBean>() { ... } instead of a raw/lambda Supplier.
  3. If you must use a factory, register the already-constructed instance with registerBean(name, instance).
  4. Ensure the factory object's class implements Supplier<ConcreteType> (not raw Supplier) so TypeUtils can read the parameter type.

Example fix

// before
Supplier raw = () -> new MyBean();
scopeBeanFactory.registerBeanFactory("myBean", raw);  // type erased
// after
scopeBeanFactory.registerBeanDefinition("myBean", MyBean.class);
// or
Supplier<MyBean> typed = () -> new MyBean();
scopeBeanFactory.registerBeanFactory("myBean", typed);
Defensive patterns

Strategy: type-guard

Type guard

// Ensure the factory exposes a reified bean type before registering
<T> boolean factoryTypeIsResolvable(Supplier<T> factory) {
    return org.apache.dubbo.common.utils.TypeUtils.getSuperGenericType(
               factory.getClass(), 0) != null;
}

Try / catch

try {
    factory.registerBeanFactory(name, supplier);
} catch (ScopeBeanException e) {
    if (e.getMessage().contains("unable to determine bean class")) {
        // fall back to registering the bean by class or by instance
        factory.registerBeanDefinition(name, MyBean.class);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling registerBeanFactory(supplier) where supplier is a plain java.util.function.Supplier, a lambda like () -> new MyBean() assigned to a raw Supplier variable, or a Supplier<T> subclass whose generic argument cannot be resolved at runtime. Also when the factory class implements Supplier with a non-generic or raw supertype.

Common situations: Registering a bean factory via reflection or a DI bridge where generics are erased; migrating code that previously used registerBean(Class) and switching to a Supplier without preserving the generic type; using method references assigned to raw Supplier fields.

Related errors


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