apache/dubbo · error · IllegalStateException
ScopeBeanFactory is destroyed
Error message
ScopeBeanFactory is destroyed
What it means
Thrown by ScopeBeanFactory.checkDestroyed whenever any mutating operation (registerBean, createAndRegisterBean, etc.) is attempted after destroy() has flipped the destroyed flag. Once a scope is destroyed its maps are cleared and further registration is illegal; Dubbo fails fast rather than registering into a dead scope.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java:387
"An error occurred when destroy bean [name=" + beanInfo.name + ", bean="
+ beanInfo.instance + "]: " + e,
e);
}
}
}
registeredBeanInfos.clear();
registeredBeanDefinitions.clear();
beanCache.clear();
}
}
public boolean isDestroyed() {
return destroyed.get();
}
private void checkDestroyed() {
if (destroyed.get()) {
throw new IllegalStateException("ScopeBeanFactory is destroyed");
}
}
static final class BeanInfo {
private final String name;
private final Object instance;
BeanInfo(String name, Object instance) {
this.name = name;
this.instance = instance;
}
}
static final class BeanDefinition<T> {
private final String name;
private final Class<T> beanClass;
private final Supplier<T> beanFactory;View on GitHub (pinned to 3a3043227f)
Solutions
- Guard every registration with if (!factory.isDestroyed()) { ... } when registration can race with shutdown.
- Ensure the ScopeModel/ApplicationModel is still alive before performing registration (check isDestroyed()).
- Cancel/await async tasks that may register beans before destroying the model, or destroy after they complete.
- In tests, do not reuse a destroyed model; create a fresh ApplicationModel for each test.
Example fix
// before
applicationModel.destroy();
factory.registerBean("late", LateBean.class); // throws
// after
if (!factory.isDestroyed()) {
factory.registerBean("late", LateBean.class);
} else {
log.warn("Skipped late registration: scope already destroyed");
} Defensive patterns
Strategy: validation
Validate before calling
// Guard registration against a destroyed scope
boolean safeRegister(ScopeBeanFactory f, String name, Class<?> type) {
if (f.isDestroyed()) {
log.warn("ScopeBeanFactory destroyed; skipping registration of {}", name);
return false;
}
f.registerBean(name, type);
return true;
} Try / catch
try {
f.registerBean(name, type);
} catch (IllegalStateException e) {
if ("ScopeBeanFactory is destroyed".equals(e.getMessage())) {
// scope already torn down; skip or re-queue the registration
} else throw e;
} Prevention
- Check isDestroyed() before any registration that can race with shutdown.
- Ensure async tasks that register beans are stopped before destroying the ScopeModel.
- Never reuse a destroyed ApplicationModel/FrameworkModel; create a fresh one.
- In tests, tear down and rebuild the model per test rather than reusing.
When it happens
Trigger: Calling registerBean / registerBeanFactory / registerBeanDefinition / getOrRegisterBean after ScopeBeanFactory.destroy() has run (typically during ApplicationModel/FrameworkModel shutdown). Also when a shutdown hook or scope-destroy races with late bean registration.
Common situations: Trying to register a bean during or after application shutdown; reusing a ScopeModel that was already destroyed; a delayed/async component attempting registration after context close; tests that tear down the model and then touch the factory.
Related errors
- register bean failed! name=${name}, type=${className}
- unable to determine bean class from factory's superclass or
- already exists bean with same name and type, name=${name}, t
- create bean instance failed, type=${className}
- expected single matching bean but found ${size} candidates f
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/85dae8947a878577.
Report an issue: GitHub.