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
- Register the bean by class instead: registerBeanDefinition(name, MyBean.class) or registerBean(name, MyBean.class).
- 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.
- If you must use a factory, register the already-constructed instance with registerBean(name, instance).
- 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
- Prefer registerBean(name, Class) or registerBeanDefinition when the type is known statically.
- Use anonymous new Supplier<ConcreteType>() { ... } instead of raw Supplier/lambda assigned to a raw variable.
- Avoid reflective wiring that erases the generic parameter of a Supplier.
- If construction needs custom logic, register an explicit BeanDefinition with both class and factory.
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
- create bean instance failed, type=${className}
- already exists bean with same name and type, name=${name}, t
- register bean failed! name=${name}, type=${className}
- expected single matching bean but found ${size} candidates f
- ScopeBeanFactory is destroyed
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/3d607751a0d06cb8.
Report an issue: GitHub.