spring-projects/spring-framework · error · FactoryBeanNotInitializedException
does not support circular references
Error message
does not support circular references
What it means
Thrown as a FactoryBeanNotInitializedException when a singleton-scoped FactoryBean is asked for its bean before it has finished initializing AND it does not opt in to early-proxy exposure. AbstractFactoryBean.getEarlySingletonInstance calls getEarlySingletonInterfaces(); if that returns null (the default), the FactoryBean declares it cannot resolve circular references and throws. Subclasses expose early-singleton interfaces to opt in to circular-reference resolution.
Solutions
- Break the circular dependency: inject one side lazily (@Lazy), use setter injection on one leg, or redesign so the FactoryBean does not depend on beans that depend on its product.
- If early exposure is acceptable, override getEarlySingletonInterfaces() in the FactoryBean to return the interfaces that the early proxy should expose.
- Disable circular references application-wide (spring.main.allow-circular-references=false) to surface such designs at startup as a deliberate error rather than a per-FactoryBean failure.
- Refactor the FactoryBean to a plain @Bean method so the container handles the singleton lifecycle and circular reference resolution.
- Move the cycle-breaking collaborator into an ObjectProvider<T> or Optional<T> so it is resolved on demand, not during initialization.
Example fix
// before: FactoryBean in a cycle, no early-singleton interfaces
public class MyFactoryBean extends AbstractFactoryBean<MyType> {
@Override protected MyType createInstance() { return new MyType(collab); }
// collab depends on MyType -> cycle
}
// after: opt in to early exposure via interfaces
@Override
protected Class<?>[] getEarlySingletonInterfaces() {
return new Class<?>[] { MyType.class };
} Defensive patterns
Strategy: validation
Validate before calling
// Detect a FactoryBean in a cycle that cannot break early
AbstractFactoryBean<?> fb = (AbstractFactoryBean<?>) factoryBean;
if (inCycle && fb.getEarlySingletonInterfaces() == null) {
throw new IllegalStateException(fb.getClass().getName() + " cannot participate in a circular reference");
} Type guard
// True if the FactoryBean opts in to early circular-reference resolution boolean supportsCycle = ((AbstractFactoryBean<?>) fb).getEarlySingletonInterfaces() != null;
Prevention
- Break circular dependencies using @Lazy, setter injection, or ObjectProvider.
- Override getEarlySingletonInterfaces() in custom FactoryBeans that may be in cycles.
- Set spring.main.allow-circular-references=false to fail fast on risky cycles.
- Prefer plain @Bean methods over custom FactoryBeans for singleton lifecycle.
When it happens
Trigger: A circular bean dependency where one of the beans in the cycle is a FactoryBean that has not overridden getEarlySingletonInterfaces() to return a non-null interface array, and Spring tries to obtain an early singleton reference to it to break the cycle. getObject() is invoked during the cycle before the FactoryBean's afterPropertiesSet has populated singletonInstance.
Common situations: Two beans mutually referencing each other where one is an AbstractFactoryBean subclass (e.g. a custom FactoryBean<Object>); spring.main.allow-circular-references=true left on while a FactoryBean in the cycle never declared early-singleton interfaces; upgrading Spring where circular reference handling was tightened; a FactoryBean whose createInstance depends (directly/indirectly) on a bean that depends back on the FactoryBean's product.
Related errors
- Cannot create scoped proxy for bean
- Failed to invoke init method
- Failed to load Class [
- Invocation of init method failed
- Lifecycle annotation requires a no-arg method:
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/f94d179139e78da2.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java:164
public final T getObject() throws Exception {
if (isSingleton()) {
T instance = this.singletonInstance;
return (instance != null ? instance : getEarlySingletonInstance());
}
else {
return createInstance();
}
}
/**
* Determine an 'early singleton' instance, exposed in case of a
* circular reference. Not called in a non-circular scenario.
*/
@SuppressWarnings("unchecked")
private T getEarlySingletonInstance() {
Class<?>[] ifcs = getEarlySingletonInterfaces();
if (ifcs == null) {
throw new FactoryBeanNotInitializedException(
getClass().getName() + " does not support circular references");
}
if (this.earlySingletonInstance == null) {
this.earlySingletonInstance = (T) Proxy.newProxyInstance(
this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler());
}
return this.earlySingletonInstance;
}
/**
* Expose the singleton instance (for access through the 'early singleton' proxy).
* @return the singleton instance that this FactoryBean holds
* @throws IllegalStateException if the singleton instance is not initialized
*/
private T getSingletonInstance() throws IllegalStateException {
T instance = this.singletonInstance;
Assert.state(instance != null, "Singleton instance not initialized yet");
return instance;View on GitHub (pinned to 69bf83ad71)